{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "6b439e84-8c6b-4126-8586-d7a1a7c7614e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 该代码文件主要为了在Purchase100上执行相关实验，验证模型自蒸馏"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "3a72ff09-8088-4a9d-b1f7-0825ff54c477",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 自蒸馏步骤：\n",
    "# 分割模型训练集，接收比例参数\n",
    "# 对训练集进行多次分割，多个影子数据集\n",
    "# 训练多个模型\n",
    "# 合并多个模型输出\n",
    "# 训练目标模型\n",
    "# 攻击\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "b61f101e-1c1e-41df-b80b-65d1e3d6eab8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "from torch.utils.data import DataLoader\n",
    "from torch.utils.data import Dataset\n",
    "from torchvision import datasets\n",
    "from torchvision import transforms\n",
    "from torchvision.transforms import ToTensor\n",
    "import torchvision.transforms as tt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn import metrics\n",
    "\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "37ddaa77-35ce-49b9-acfd-a7799aadd9a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入自己创建的python文件\n",
    "import sys\n",
    "sys.path.append(\"..\") # Adds higher directory to python modules path.\n",
    "from frame.DataProcess import *\n",
    "from frame.TrainUtil import *\n",
    "from frame.LIRAAttack import *\n",
    "from frame.AttackUtil import *\n",
    "from frame.ShadowAttack import *\n",
    "from frame.ThresholdAttack import *\n",
    "from frame.LabelAttack import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4636a18e-244e-4a21-ba21-591c0295ce7a",
   "metadata": {},
   "outputs": [],
   "source": [
    "LEARNING_RATE = 1e-3\n",
    "BATCH_SIZE = 128\n",
    "MODEL = 'CNN'\n",
    "EPOCHS = 50\n",
    "DATA_NAME = 'MNIST' \n",
    "weight_dir = os.path.join('..', 'weights_for_exp', DATA_NAME)\n",
    "weight_dir = os.path.join('..', 'weights_for_exp', DATA_NAME)\n",
    "num_shadowsets = 100\n",
    "seed = 0\n",
    "prop_keep = 0.5\n",
    "\n",
    "model_transform = transforms.Compose([\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize(mean=[0.5], std=[0.5])\n",
    "    ])\n",
    "attack_transform = transforms.Compose([])\n",
    "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
    "\n",
    "# 影子模型攻击相关参数\n",
    "sha_models = [1,2,3] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]\n",
    "tar_model = 0\n",
    "attack_class = False #是否针对每个类别分别攻击\n",
    "attack_lr = 5e-4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e8818f5c-0cf8-4635-a3d6-292f91f14d75",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 加载完整的训练数据集\n",
    "X_data, Y_data, train_keep = load_MNIST_keep(num_shadowsets, prop_keep, seed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1754e859-f23b-4a3c-8666-b2ce06c2b8f8",
   "metadata": {},
   "outputs": [],
   "source": [
    "all_data = CustomDataset(X_data, Y_data, model_transform)\n",
    "all_dataloader = DataLoader(all_data, batch_size=BATCH_SIZE, shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "0e839f4d-93e7-48f0-af07-349ebef049a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "batch_size = BATCH_SIZE\n",
    "model = MODEL\n",
    "epochs = EPOCHS\n",
    "data_name = DATA_NAME \n",
    "weight_part = \"{}_{}_epoch{}_model\".format(data_name, model, epochs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "5ef57ecf-b753-43a3-ae9a-f6a1f05171dc",
   "metadata": {},
   "outputs": [],
   "source": [
    "loss_data_all = np.load('../outputs_save/MNIST_loss.npy')\n",
    "score_all = np.load('../outputs_save/MNIST_score.npy')\n",
    "conf_data_all = np.load('../outputs_save/MNIST_conf.npy')\n",
    "pri_risk_all = get_risk_score(loss_data_all, train_keep)\n",
    "pri_risk_rank = np.argsort(pri_risk_all)\n",
    "pri_risk_rank = np.flip(pri_risk_rank)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a9c906af-6272-42a1-b6c0-9ff69c5208f9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " Error: \n",
      " Accuracy: 99.5%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.3%  \n",
      "\n",
      "(60000, 10) (60000,) (60000,)\n",
      " Error: \n",
      " Accuracy: 99.7%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.2%  \n",
      "\n",
      "(60000, 10) (60000,) (60000,)\n",
      " Error: \n",
      " Accuracy: 99.7%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.2%  \n",
      "\n",
      "(60000, 10) (60000,) (60000,)\n",
      " Error: \n",
      " Accuracy: 99.7%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.3%  \n",
      "\n",
      "test data: (60000, 10) (60000,) (60000,)\n",
      "(180000, 10) (180000,)\n",
      "Attack_NN(\n",
      "  (linear_relu_stack): Sequential(\n",
      "    (0): Linear(in_features=3, out_features=128, bias=True)\n",
      "    (1): ReLU()\n",
      "    (2): Linear(in_features=128, out_features=64, bias=True)\n",
      "    (3): ReLU()\n",
      "    (4): Linear(in_features=64, out_features=1, bias=True)\n",
      "  )\n",
      ")\n",
      "Epoch 1\n",
      "-------------------------------\n",
      "loss: 0.709486  [  128/180000]\n",
      "loss: 0.692064  [12928/180000]\n",
      "loss: 0.691625  [25728/180000]\n",
      "loss: 0.694382  [38528/180000]\n",
      "loss: 0.694223  [51328/180000]\n",
      "loss: 0.692802  [64128/180000]\n",
      "loss: 0.694210  [76928/180000]\n",
      "loss: 0.693148  [89728/180000]\n",
      "loss: 0.690833  [102528/180000]\n",
      "loss: 0.690984  [115328/180000]\n",
      "loss: 0.695159  [128128/180000]\n",
      "loss: 0.690577  [140928/180000]\n",
      "loss: 0.691816  [153728/180000]\n",
      "loss: 0.692381  [166528/180000]\n",
      "loss: 0.693840  [179328/180000]\n",
      "Epoch 2\n",
      "-------------------------------\n",
      "loss: 0.691196  [  128/180000]\n",
      "loss: 0.690397  [12928/180000]\n",
      "loss: 0.691131  [25728/180000]\n",
      "loss: 0.694064  [38528/180000]\n",
      "loss: 0.689865  [51328/180000]\n",
      "loss: 0.690720  [64128/180000]\n",
      "loss: 0.694982  [76928/180000]\n",
      "loss: 0.699116  [89728/180000]\n",
      "loss: 0.695486  [102528/180000]\n",
      "loss: 0.692216  [115328/180000]\n",
      "loss: 0.692479  [128128/180000]\n",
      "loss: 0.688681  [140928/180000]\n",
      "loss: 0.692388  [153728/180000]\n",
      "loss: 0.697769  [166528/180000]\n",
      "loss: 0.690353  [179328/180000]\n",
      "Epoch 3\n",
      "-------------------------------\n",
      "loss: 0.687740  [  128/180000]\n",
      "loss: 0.693787  [12928/180000]\n",
      "loss: 0.694610  [25728/180000]\n",
      "loss: 0.693235  [38528/180000]\n",
      "loss: 0.695670  [51328/180000]\n",
      "loss: 0.690372  [64128/180000]\n",
      "loss: 0.693269  [76928/180000]\n",
      "loss: 0.694100  [89728/180000]\n",
      "loss: 0.687817  [102528/180000]\n",
      "loss: 0.688478  [115328/180000]\n",
      "loss: 0.693332  [128128/180000]\n",
      "loss: 0.692550  [140928/180000]\n",
      "loss: 0.695064  [153728/180000]\n",
      "loss: 0.698751  [166528/180000]\n",
      "loss: 0.688268  [179328/180000]\n",
      "Epoch 4\n",
      "-------------------------------\n",
      "loss: 0.692791  [  128/180000]\n",
      "loss: 0.692328  [12928/180000]\n",
      "loss: 0.692136  [25728/180000]\n",
      "loss: 0.693377  [38528/180000]\n",
      "loss: 0.696498  [51328/180000]\n",
      "loss: 0.693506  [64128/180000]\n",
      "loss: 0.689788  [76928/180000]\n",
      "loss: 0.689286  [89728/180000]\n",
      "loss: 0.694985  [102528/180000]\n",
      "loss: 0.688165  [115328/180000]\n",
      "loss: 0.700057  [128128/180000]\n",
      "loss: 0.691244  [140928/180000]\n",
      "loss: 0.692378  [153728/180000]\n",
      "loss: 0.694244  [166528/180000]\n",
      "loss: 0.696712  [179328/180000]\n",
      "Epoch 5\n",
      "-------------------------------\n",
      "loss: 0.689780  [  128/180000]\n",
      "loss: 0.692811  [12928/180000]\n",
      "loss: 0.696039  [25728/180000]\n",
      "loss: 0.693207  [38528/180000]\n",
      "loss: 0.695987  [51328/180000]\n",
      "loss: 0.692211  [64128/180000]\n",
      "loss: 0.696629  [76928/180000]\n",
      "loss: 0.691165  [89728/180000]\n",
      "loss: 0.690771  [102528/180000]\n",
      "loss: 0.690704  [115328/180000]\n",
      "loss: 0.689802  [128128/180000]\n",
      "loss: 0.695963  [140928/180000]\n",
      "loss: 0.691468  [153728/180000]\n",
      "loss: 0.696561  [166528/180000]\n",
      "loss: 0.693830  [179328/180000]\n",
      "Epoch 6\n",
      "-------------------------------\n",
      "loss: 0.693897  [  128/180000]\n",
      "loss: 0.693069  [12928/180000]\n",
      "loss: 0.692702  [25728/180000]\n",
      "loss: 0.691181  [38528/180000]\n",
      "loss: 0.693866  [51328/180000]\n",
      "loss: 0.690523  [64128/180000]\n",
      "loss: 0.692825  [76928/180000]\n",
      "loss: 0.689167  [89728/180000]\n",
      "loss: 0.692693  [102528/180000]\n",
      "loss: 0.691291  [115328/180000]\n",
      "loss: 0.689292  [128128/180000]\n",
      "loss: 0.691098  [140928/180000]\n",
      "loss: 0.694555  [153728/180000]\n",
      "loss: 0.694541  [166528/180000]\n",
      "loss: 0.691323  [179328/180000]\n",
      "Epoch 7\n",
      "-------------------------------\n",
      "loss: 0.693048  [  128/180000]\n",
      "loss: 0.696728  [12928/180000]\n",
      "loss: 0.692363  [25728/180000]\n",
      "loss: 0.694277  [38528/180000]\n",
      "loss: 0.700209  [51328/180000]\n",
      "loss: 0.688419  [64128/180000]\n",
      "loss: 0.692888  [76928/180000]\n",
      "loss: 0.691734  [89728/180000]\n",
      "loss: 0.693728  [102528/180000]\n",
      "loss: 0.689782  [115328/180000]\n",
      "loss: 0.695806  [128128/180000]\n",
      "loss: 0.689721  [140928/180000]\n",
      "loss: 0.694704  [153728/180000]\n",
      "loss: 0.693127  [166528/180000]\n",
      "loss: 0.693367  [179328/180000]\n",
      "Epoch 8\n",
      "-------------------------------\n",
      "loss: 0.695689  [  128/180000]\n",
      "loss: 0.696585  [12928/180000]\n",
      "loss: 0.691114  [25728/180000]\n",
      "loss: 0.696670  [38528/180000]\n",
      "loss: 0.690679  [51328/180000]\n",
      "loss: 0.687525  [64128/180000]\n",
      "loss: 0.691232  [76928/180000]\n",
      "loss: 0.693505  [89728/180000]\n",
      "loss: 0.695156  [102528/180000]\n",
      "loss: 0.692425  [115328/180000]\n",
      "loss: 0.694931  [128128/180000]\n",
      "loss: 0.691275  [140928/180000]\n",
      "loss: 0.693280  [153728/180000]\n",
      "loss: 0.692707  [166528/180000]\n",
      "loss: 0.695097  [179328/180000]\n",
      "Epoch 9\n",
      "-------------------------------\n",
      "loss: 0.689559  [  128/180000]\n",
      "loss: 0.693842  [12928/180000]\n",
      "loss: 0.691926  [25728/180000]\n",
      "loss: 0.697681  [38528/180000]\n",
      "loss: 0.691520  [51328/180000]\n",
      "loss: 0.693937  [64128/180000]\n",
      "loss: 0.694706  [76928/180000]\n",
      "loss: 0.693023  [89728/180000]\n",
      "loss: 0.694826  [102528/180000]\n",
      "loss: 0.689010  [115328/180000]\n",
      "loss: 0.695995  [128128/180000]\n",
      "loss: 0.691810  [140928/180000]\n",
      "loss: 0.693068  [153728/180000]\n",
      "loss: 0.691748  [166528/180000]\n",
      "loss: 0.692217  [179328/180000]\n",
      "Epoch 10\n",
      "-------------------------------\n",
      "loss: 0.695433  [  128/180000]\n",
      "loss: 0.687608  [12928/180000]\n",
      "loss: 0.692251  [25728/180000]\n",
      "loss: 0.694860  [38528/180000]\n",
      "loss: 0.695400  [51328/180000]\n",
      "loss: 0.693037  [64128/180000]\n",
      "loss: 0.696070  [76928/180000]\n",
      "loss: 0.690661  [89728/180000]\n",
      "loss: 0.701570  [102528/180000]\n",
      "loss: 0.689363  [115328/180000]\n",
      "loss: 0.693249  [128128/180000]\n",
      "loss: 0.689388  [140928/180000]\n",
      "loss: 0.690602  [153728/180000]\n",
      "loss: 0.696084  [166528/180000]\n",
      "loss: 0.692603  [179328/180000]\n",
      "Epoch 11\n",
      "-------------------------------\n",
      "loss: 0.693514  [  128/180000]\n",
      "loss: 0.690370  [12928/180000]\n",
      "loss: 0.693347  [25728/180000]\n",
      "loss: 0.689217  [38528/180000]\n",
      "loss: 0.690096  [51328/180000]\n",
      "loss: 0.694362  [64128/180000]\n",
      "loss: 0.696809  [76928/180000]\n",
      "loss: 0.695130  [89728/180000]\n",
      "loss: 0.688817  [102528/180000]\n",
      "loss: 0.690835  [115328/180000]\n",
      "loss: 0.687433  [128128/180000]\n",
      "loss: 0.696118  [140928/180000]\n",
      "loss: 0.699938  [153728/180000]\n",
      "loss: 0.693864  [166528/180000]\n",
      "loss: 0.686032  [179328/180000]\n",
      "Epoch 12\n",
      "-------------------------------\n",
      "loss: 0.698260  [  128/180000]\n",
      "loss: 0.698204  [12928/180000]\n",
      "loss: 0.691202  [25728/180000]\n",
      "loss: 0.693919  [38528/180000]\n",
      "loss: 0.694324  [51328/180000]\n",
      "loss: 0.692660  [64128/180000]\n",
      "loss: 0.692396  [76928/180000]\n",
      "loss: 0.695559  [89728/180000]\n",
      "loss: 0.688929  [102528/180000]\n",
      "loss: 0.693061  [115328/180000]\n",
      "loss: 0.698149  [128128/180000]\n",
      "loss: 0.690332  [140928/180000]\n",
      "loss: 0.685428  [153728/180000]\n",
      "loss: 0.696527  [166528/180000]\n",
      "loss: 0.693719  [179328/180000]\n",
      "Epoch 13\n",
      "-------------------------------\n",
      "loss: 0.693910  [  128/180000]\n",
      "loss: 0.692847  [12928/180000]\n",
      "loss: 0.691884  [25728/180000]\n",
      "loss: 0.694597  [38528/180000]\n",
      "loss: 0.689134  [51328/180000]\n",
      "loss: 0.692737  [64128/180000]\n",
      "loss: 0.689843  [76928/180000]\n",
      "loss: 0.697940  [89728/180000]\n",
      "loss: 0.691280  [102528/180000]\n",
      "loss: 0.690379  [115328/180000]\n",
      "loss: 0.693030  [128128/180000]\n",
      "loss: 0.691449  [140928/180000]\n",
      "loss: 0.688500  [153728/180000]\n",
      "loss: 0.699651  [166528/180000]\n",
      "loss: 0.692072  [179328/180000]\n",
      "Epoch 14\n",
      "-------------------------------\n",
      "loss: 0.690418  [  128/180000]\n",
      "loss: 0.686870  [12928/180000]\n",
      "loss: 0.689619  [25728/180000]\n",
      "loss: 0.693861  [38528/180000]\n",
      "loss: 0.689311  [51328/180000]\n",
      "loss: 0.693400  [64128/180000]\n",
      "loss: 0.695343  [76928/180000]\n",
      "loss: 0.691298  [89728/180000]\n",
      "loss: 0.688339  [102528/180000]\n",
      "loss: 0.689135  [115328/180000]\n",
      "loss: 0.694267  [128128/180000]\n",
      "loss: 0.693833  [140928/180000]\n",
      "loss: 0.691908  [153728/180000]\n",
      "loss: 0.693246  [166528/180000]\n",
      "loss: 0.693040  [179328/180000]\n",
      "Epoch 15\n",
      "-------------------------------\n",
      "loss: 0.694029  [  128/180000]\n",
      "loss: 0.695422  [12928/180000]\n",
      "loss: 0.695456  [25728/180000]\n",
      "loss: 0.691520  [38528/180000]\n",
      "loss: 0.689738  [51328/180000]\n",
      "loss: 0.696576  [64128/180000]\n",
      "loss: 0.694677  [76928/180000]\n",
      "loss: 0.694809  [89728/180000]\n",
      "loss: 0.685918  [102528/180000]\n",
      "loss: 0.690739  [115328/180000]\n",
      "loss: 0.693384  [128128/180000]\n",
      "loss: 0.691204  [140928/180000]\n",
      "loss: 0.696965  [153728/180000]\n",
      "loss: 0.691740  [166528/180000]\n",
      "loss: 0.690773  [179328/180000]\n",
      "Epoch 16\n",
      "-------------------------------\n",
      "loss: 0.692651  [  128/180000]\n",
      "loss: 0.688699  [12928/180000]\n",
      "loss: 0.694111  [25728/180000]\n",
      "loss: 0.689707  [38528/180000]\n",
      "loss: 0.695413  [51328/180000]\n",
      "loss: 0.692119  [64128/180000]\n",
      "loss: 0.695679  [76928/180000]\n",
      "loss: 0.694604  [89728/180000]\n",
      "loss: 0.691805  [102528/180000]\n",
      "loss: 0.695980  [115328/180000]\n",
      "loss: 0.695673  [128128/180000]\n",
      "loss: 0.696557  [140928/180000]\n",
      "loss: 0.695461  [153728/180000]\n",
      "loss: 0.692808  [166528/180000]\n",
      "loss: 0.689687  [179328/180000]\n",
      "Epoch 17\n",
      "-------------------------------\n",
      "loss: 0.692986  [  128/180000]\n",
      "loss: 0.696060  [12928/180000]\n",
      "loss: 0.696698  [25728/180000]\n",
      "loss: 0.692824  [38528/180000]\n",
      "loss: 0.689111  [51328/180000]\n",
      "loss: 0.690554  [64128/180000]\n",
      "loss: 0.692420  [76928/180000]\n",
      "loss: 0.688734  [89728/180000]\n",
      "loss: 0.690388  [102528/180000]\n",
      "loss: 0.697142  [115328/180000]\n",
      "loss: 0.691138  [128128/180000]\n",
      "loss: 0.695600  [140928/180000]\n",
      "loss: 0.691184  [153728/180000]\n",
      "loss: 0.695279  [166528/180000]\n",
      "loss: 0.689068  [179328/180000]\n",
      "Epoch 18\n",
      "-------------------------------\n",
      "loss: 0.690957  [  128/180000]\n",
      "loss: 0.695191  [12928/180000]\n",
      "loss: 0.693109  [25728/180000]\n",
      "loss: 0.689770  [38528/180000]\n",
      "loss: 0.699825  [51328/180000]\n",
      "loss: 0.702984  [64128/180000]\n",
      "loss: 0.689504  [76928/180000]\n",
      "loss: 0.694069  [89728/180000]\n",
      "loss: 0.688612  [102528/180000]\n",
      "loss: 0.683218  [115328/180000]\n",
      "loss: 0.690326  [128128/180000]\n",
      "loss: 0.688851  [140928/180000]\n",
      "loss: 0.692655  [153728/180000]\n",
      "loss: 0.693965  [166528/180000]\n",
      "loss: 0.692701  [179328/180000]\n",
      "Epoch 19\n",
      "-------------------------------\n",
      "loss: 0.705239  [  128/180000]\n",
      "loss: 0.689934  [12928/180000]\n",
      "loss: 0.693941  [25728/180000]\n",
      "loss: 0.692089  [38528/180000]\n",
      "loss: 0.693352  [51328/180000]\n",
      "loss: 0.691567  [64128/180000]\n",
      "loss: 0.694364  [76928/180000]\n",
      "loss: 0.691269  [89728/180000]\n",
      "loss: 0.702098  [102528/180000]\n",
      "loss: 0.695573  [115328/180000]\n",
      "loss: 0.692181  [128128/180000]\n",
      "loss: 0.694416  [140928/180000]\n",
      "loss: 0.694932  [153728/180000]\n",
      "loss: 0.690060  [166528/180000]\n",
      "loss: 0.691051  [179328/180000]\n",
      "Epoch 20\n",
      "-------------------------------\n",
      "loss: 0.694136  [  128/180000]\n",
      "loss: 0.688354  [12928/180000]\n",
      "loss: 0.688225  [25728/180000]\n",
      "loss: 0.690239  [38528/180000]\n",
      "loss: 0.691342  [51328/180000]\n",
      "loss: 0.691373  [64128/180000]\n",
      "loss: 0.688856  [76928/180000]\n",
      "loss: 0.695547  [89728/180000]\n",
      "loss: 0.688371  [102528/180000]\n",
      "loss: 0.691472  [115328/180000]\n",
      "loss: 0.701494  [128128/180000]\n",
      "loss: 0.698736  [140928/180000]\n",
      "loss: 0.693004  [153728/180000]\n",
      "loss: 0.693807  [166528/180000]\n",
      "loss: 0.698260  [179328/180000]\n",
      "Epoch 21\n",
      "-------------------------------\n",
      "loss: 0.691747  [  128/180000]\n",
      "loss: 0.691374  [12928/180000]\n",
      "loss: 0.688234  [25728/180000]\n",
      "loss: 0.689085  [38528/180000]\n",
      "loss: 0.687725  [51328/180000]\n",
      "loss: 0.686775  [64128/180000]\n",
      "loss: 0.688285  [76928/180000]\n",
      "loss: 0.688196  [89728/180000]\n",
      "loss: 0.692966  [102528/180000]\n",
      "loss: 0.685403  [115328/180000]\n",
      "loss: 0.690994  [128128/180000]\n",
      "loss: 0.699215  [140928/180000]\n",
      "loss: 0.684506  [153728/180000]\n",
      "loss: 0.696762  [166528/180000]\n",
      "loss: 0.695011  [179328/180000]\n",
      "Epoch 22\n",
      "-------------------------------\n",
      "loss: 0.687847  [  128/180000]\n",
      "loss: 0.696360  [12928/180000]\n",
      "loss: 0.686298  [25728/180000]\n",
      "loss: 0.687578  [38528/180000]\n",
      "loss: 0.693148  [51328/180000]\n",
      "loss: 0.693472  [64128/180000]\n",
      "loss: 0.690168  [76928/180000]\n",
      "loss: 0.699310  [89728/180000]\n",
      "loss: 0.694780  [102528/180000]\n",
      "loss: 0.686224  [115328/180000]\n",
      "loss: 0.689280  [128128/180000]\n",
      "loss: 0.686200  [140928/180000]\n",
      "loss: 0.687767  [153728/180000]\n",
      "loss: 0.691580  [166528/180000]\n",
      "loss: 0.693189  [179328/180000]\n",
      "Epoch 23\n",
      "-------------------------------\n",
      "loss: 0.694324  [  128/180000]\n",
      "loss: 0.693727  [12928/180000]\n",
      "loss: 0.692447  [25728/180000]\n",
      "loss: 0.688553  [38528/180000]\n",
      "loss: 0.685753  [51328/180000]\n",
      "loss: 0.692776  [64128/180000]\n",
      "loss: 0.678890  [76928/180000]\n",
      "loss: 0.696396  [89728/180000]\n",
      "loss: 0.690879  [102528/180000]\n",
      "loss: 0.694116  [115328/180000]\n",
      "loss: 0.691092  [128128/180000]\n",
      "loss: 0.697657  [140928/180000]\n",
      "loss: 0.695633  [153728/180000]\n",
      "loss: 0.690188  [166528/180000]\n",
      "loss: 0.689028  [179328/180000]\n",
      "Epoch 24\n",
      "-------------------------------\n",
      "loss: 0.698091  [  128/180000]\n",
      "loss: 0.694780  [12928/180000]\n",
      "loss: 0.683664  [25728/180000]\n",
      "loss: 0.692798  [38528/180000]\n",
      "loss: 0.689225  [51328/180000]\n",
      "loss: 0.694796  [64128/180000]\n",
      "loss: 0.691302  [76928/180000]\n",
      "loss: 0.687694  [89728/180000]\n",
      "loss: 0.694120  [102528/180000]\n",
      "loss: 0.691635  [115328/180000]\n",
      "loss: 0.690084  [128128/180000]\n",
      "loss: 0.690058  [140928/180000]\n",
      "loss: 0.696736  [153728/180000]\n",
      "loss: 0.695278  [166528/180000]\n",
      "loss: 0.691011  [179328/180000]\n",
      "Epoch 25\n",
      "-------------------------------\n",
      "loss: 0.691920  [  128/180000]\n",
      "loss: 0.693212  [12928/180000]\n",
      "loss: 0.691628  [25728/180000]\n",
      "loss: 0.693428  [38528/180000]\n",
      "loss: 0.693174  [51328/180000]\n",
      "loss: 0.696229  [64128/180000]\n",
      "loss: 0.698710  [76928/180000]\n",
      "loss: 0.689031  [89728/180000]\n",
      "loss: 0.695241  [102528/180000]\n",
      "loss: 0.686597  [115328/180000]\n",
      "loss: 0.688694  [128128/180000]\n",
      "loss: 0.696788  [140928/180000]\n",
      "loss: 0.692141  [153728/180000]\n",
      "loss: 0.692450  [166528/180000]\n",
      "loss: 0.692424  [179328/180000]\n",
      "Epoch 26\n",
      "-------------------------------\n",
      "loss: 0.696596  [  128/180000]\n",
      "loss: 0.693209  [12928/180000]\n",
      "loss: 0.696493  [25728/180000]\n",
      "loss: 0.690788  [38528/180000]\n",
      "loss: 0.690753  [51328/180000]\n",
      "loss: 0.698974  [64128/180000]\n",
      "loss: 0.695675  [76928/180000]\n",
      "loss: 0.691012  [89728/180000]\n",
      "loss: 0.690832  [102528/180000]\n",
      "loss: 0.694027  [115328/180000]\n",
      "loss: 0.700888  [128128/180000]\n",
      "loss: 0.691705  [140928/180000]\n",
      "loss: 0.696187  [153728/180000]\n",
      "loss: 0.693403  [166528/180000]\n",
      "loss: 0.691775  [179328/180000]\n",
      "Epoch 27\n",
      "-------------------------------\n",
      "loss: 0.691136  [  128/180000]\n",
      "loss: 0.693940  [12928/180000]\n",
      "loss: 0.696630  [25728/180000]\n",
      "loss: 0.689307  [38528/180000]\n",
      "loss: 0.689646  [51328/180000]\n",
      "loss: 0.698609  [64128/180000]\n",
      "loss: 0.694049  [76928/180000]\n",
      "loss: 0.691573  [89728/180000]\n",
      "loss: 0.693244  [102528/180000]\n",
      "loss: 0.688515  [115328/180000]\n",
      "loss: 0.692850  [128128/180000]\n",
      "loss: 0.684993  [140928/180000]\n",
      "loss: 0.690460  [153728/180000]\n",
      "loss: 0.697514  [166528/180000]\n",
      "loss: 0.688514  [179328/180000]\n",
      "Epoch 28\n",
      "-------------------------------\n",
      "loss: 0.691946  [  128/180000]\n",
      "loss: 0.690563  [12928/180000]\n",
      "loss: 0.699170  [25728/180000]\n",
      "loss: 0.693413  [38528/180000]\n",
      "loss: 0.688768  [51328/180000]\n",
      "loss: 0.695606  [64128/180000]\n",
      "loss: 0.697041  [76928/180000]\n",
      "loss: 0.691249  [89728/180000]\n",
      "loss: 0.694898  [102528/180000]\n",
      "loss: 0.701449  [115328/180000]\n",
      "loss: 0.691688  [128128/180000]\n",
      "loss: 0.691763  [140928/180000]\n",
      "loss: 0.691102  [153728/180000]\n",
      "loss: 0.692023  [166528/180000]\n",
      "loss: 0.694486  [179328/180000]\n",
      "Epoch 29\n",
      "-------------------------------\n",
      "loss: 0.697896  [  128/180000]\n",
      "loss: 0.692686  [12928/180000]\n",
      "loss: 0.686434  [25728/180000]\n",
      "loss: 0.687965  [38528/180000]\n",
      "loss: 0.696436  [51328/180000]\n",
      "loss: 0.691683  [64128/180000]\n",
      "loss: 0.691641  [76928/180000]\n",
      "loss: 0.690549  [89728/180000]\n",
      "loss: 0.689165  [102528/180000]\n",
      "loss: 0.689013  [115328/180000]\n",
      "loss: 0.688402  [128128/180000]\n",
      "loss: 0.687730  [140928/180000]\n",
      "loss: 0.694204  [153728/180000]\n",
      "loss: 0.689799  [166528/180000]\n",
      "loss: 0.692724  [179328/180000]\n",
      "Epoch 30\n",
      "-------------------------------\n",
      "loss: 0.692948  [  128/180000]\n",
      "loss: 0.690847  [12928/180000]\n",
      "loss: 0.687473  [25728/180000]\n",
      "loss: 0.691729  [38528/180000]\n",
      "loss: 0.692248  [51328/180000]\n",
      "loss: 0.694554  [64128/180000]\n",
      "loss: 0.691906  [76928/180000]\n",
      "loss: 0.686548  [89728/180000]\n",
      "loss: 0.692564  [102528/180000]\n",
      "loss: 0.686222  [115328/180000]\n",
      "loss: 0.702730  [128128/180000]\n",
      "loss: 0.690031  [140928/180000]\n",
      "loss: 0.690135  [153728/180000]\n",
      "loss: 0.692797  [166528/180000]\n",
      "loss: 0.687036  [179328/180000]\n",
      "Done!\n",
      "Train data:\n",
      "AUC value is: 0.506688243482929\n",
      "Accuracy is: 0.5011166666666667\n",
      "Test data:\n",
      "AUC value is: 0.5061134578146382\n",
      "Accuracy is: 0.49978333333333336\n"
     ]
    }
   ],
   "source": [
    "# 训练影子攻击模型\n",
    "attack_model = shadow_attack(sha_models=sha_models, tar_model=tar_model, model_num=num_shadowsets, weight_dir=weight_dir, data_name=DATA_NAME, model=MODEL, model_transform=model_transform, \n",
    "                  model_epochs=EPOCHS, batch_size=BATCH_SIZE, learning_rate=attack_lr, attack_epochs=30, attack_transform=attack_transform, \n",
    "                  device=device, prop_keep=0.5, top_k=3, attack_class=attack_class)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "92cd699f-db12-4feb-91a4-18fbd0f0890e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "6cf49ce4-482f-4544-b632-1d8193afc222",
   "metadata": {},
   "outputs": [],
   "source": [
    "mem_label = train_keep[0]\n",
    "mem_data = np.where(mem_label==True)[0]\n",
    "train_num = mem_label.sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "505a8b97-2514-4e2a-a69f-8b610398affc",
   "metadata": {},
   "outputs": [],
   "source": [
    "dist_num = 50\n",
    "np.random.seed(seed)\n",
    "keep_matrix = np.random.uniform(0,1,size=(dist_num, train_num))\n",
    "order = keep_matrix.argsort(0)\n",
    "dist_keep = order < int(prop_keep * dist_num)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "e208aa42-6643-4679-bfb9-061494c3d833",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# for i in range(dist_num):\n",
    "#     dis_train = mem_data[dist_keep[i]]\n",
    "#     x = X_data[dis_train]\n",
    "#     y = Y_data[dis_train]\n",
    "#     train_data = CustomDataset(x, y, model_transform)\n",
    "#     train_dataloader = DataLoader(train_data, batch_size=batch_size)\n",
    "#     ReferenceModel = globals()['create_{}_model'.format(model)](x.shape[1], y.max()+1)\n",
    "#     ReferenceModel.to(device)\n",
    "#     loss_fn = nn.CrossEntropyLoss()\n",
    "#     optimizer = torch.optim.Adam(ReferenceModel.parameters(), lr=LEARNING_RATE)\n",
    "#     for t in range(epochs):\n",
    "#         print(f\"Epoch {t+1}\\n-------------------------------\")\n",
    "#         train(train_dataloader, ReferenceModel, loss_fn, optimizer, device)\n",
    "#     print(\"Done!\")\n",
    "#     weight_path = os.path.join(weight_dir, \"{}_{}_epoch{}_dist0_model{}.pth\".format(data_name, model, epochs, i))\n",
    "#     torch.save(ReferenceModel.state_dict(), weight_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13b51bda-5bfe-4058-adc4-760981cb2f72",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "da45bfa9-fd37-4386-8937-ea857f86b9f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = X_data[mem_label]\n",
    "y = Y_data[mem_label]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2bd26053-2535-4b0d-83bf-5d37e7739722",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.7%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.1%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.1%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.8%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.7%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.5%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.0%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.0%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 99.0%  \n",
      "\n"
     ]
    }
   ],
   "source": [
    "weight_part = \"{}_{}_epoch{}_dist0_model\".format(data_name, model, epochs)\n",
    "conf_data_train, label_data_train, _ = load_score_data_all(x, y, weight_dir, dist_num, data_name, model, weight_part, model_transform, batch_size, device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5d2d5f7b-41cd-45cb-830d-92a8f6293764",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "34907a72-da6e-4d85-9714-643f0214558e",
   "metadata": {},
   "outputs": [],
   "source": [
    "conf_in = []\n",
    "conf_out = []\n",
    "for i in range(conf_data_train.shape[1]):\n",
    "    conf_in.append((conf_data_train[dist_keep[:,i],i]))\n",
    "    conf_out.append((conf_data_train[~dist_keep[:,i],i]))\n",
    "conf_in = np.array(conf_in)\n",
    "conf_out = np.array(conf_out)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "d6e96ff9-8451-4de5-a706-dc95149569ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "conf_in_mean = np.median(conf_in, 1)\n",
    "conf_out_mean = np.median(conf_out, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "432b54fa-a658-4b22-8ca9-8b8845b8a882",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 混合策略研究\n",
    "# 基于隐私风险混合\n",
    "# 加载隐私风险"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "2b26cdca-b753-443c-b7da-845398d281ce",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000,)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pri_risk_all.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "3b5b8330-ed31-43aa-8fed-d31c0232436f",
   "metadata": {},
   "outputs": [],
   "source": [
    "y_onehot = np.eye(10, dtype=np.float64)[Y_data[mem_label]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "17a7ea84-de16-4e16-a097-a9683ccb0cea",
   "metadata": {},
   "outputs": [],
   "source": [
    "def cross_entropy(y_pred, y_true):\n",
    "    ce = -y_true*np.log(y_pred+1e-30)\n",
    "    ce = np.sum(ce, axis=0)\n",
    "    return ce\n",
    "\n",
    "def cal_risk(conf_in, conf_out, y_true):\n",
    "    loss_in = cross_entropy(conf_in, y_true)\n",
    "    loss_out = cross_entropy(conf_out, y_true)\n",
    "    risk = loss_out - loss_in\n",
    "    if risk < 0:\n",
    "        risk = -risk\n",
    "    return risk\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "8ab46753-4384-4eeb-bb44-912561a198e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "test_dataset = datasets.MNIST(root='../datasets/mnist', train=False, transform=None, download=True)\n",
    "x_test_data = test_dataset.data.numpy()\n",
    "y_test_data = test_dataset.targets.numpy()\n",
    "test_data = CustomDataset(x_test_data, y_test_data, model_transform)\n",
    "test_dataloader = DataLoader(test_data, batch_size=batch_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "f6f5f275-8d5f-4a77-9275-65877a45d5ce",
   "metadata": {},
   "outputs": [],
   "source": [
    "def label_fix(risk_bound, k_init, y_onehot, conf_out_mean, pri_risk_all, mem_data):\n",
    "    y_soft = y_onehot.copy()\n",
    "    for i in range(y_onehot.shape[0]):\n",
    "        risk = pri_risk_all[mem_data[i]]\n",
    "        if risk < risk_bound:\n",
    "            k = k_init\n",
    "            y_soft[i] = k*y_onehot[i] + (1-k)*conf_out_mean[i]\n",
    "        else:\n",
    "            k = k_init\n",
    "            soft_label = k*y_onehot[i] + (1-k)*conf_out_mean[i]\n",
    "            risk_thre = risk_bound\n",
    "            risk = cal_risk(soft_label, conf_out_mean[i], y_onehot[i])\n",
    "            while(risk>risk_thre and k>0.01):\n",
    "                k -= 0.01\n",
    "                soft_label = k*y_onehot[i] + (1-k)*conf_out_mean[i]\n",
    "                risk = cal_risk(soft_label, conf_out_mean[i], y_onehot[i])\n",
    "            y_soft[i] = soft_label\n",
    "            # print(k)\n",
    "    return conf_out_mean"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "a24a3121-bfb1-4e21-94d9-d1c61c4f67a5",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1\n",
      "-------------------------------\n",
      "loss: 2.306501  [  128/30013]\n",
      "loss: 0.399777  [12928/30013]\n",
      "loss: 0.196370  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 83.3%\n",
      "Epoch 2\n",
      "-------------------------------\n",
      "loss: 0.195131  [  128/30013]\n",
      "loss: 0.190416  [12928/30013]\n",
      "loss: 0.110653  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.0%\n",
      "Epoch 3\n",
      "-------------------------------\n",
      "loss: 0.146452  [  128/30013]\n",
      "loss: 0.144430  [12928/30013]\n",
      "loss: 0.067597  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.3%\n",
      "Epoch 4\n",
      "-------------------------------\n",
      "loss: 0.119131  [  128/30013]\n",
      "loss: 0.131989  [12928/30013]\n",
      "loss: 0.060401  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.8%\n",
      "Epoch 5\n",
      "-------------------------------\n",
      "loss: 0.110070  [  128/30013]\n",
      "loss: 0.095519  [12928/30013]\n",
      "loss: 0.059627  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 98.3%\n",
      "Epoch 6\n",
      "-------------------------------\n",
      "loss: 0.091266  [  128/30013]\n",
      "loss: 0.072841  [12928/30013]\n",
      "loss: 0.048969  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 98.6%\n",
      "Epoch 7\n",
      "-------------------------------\n",
      "loss: 0.074741  [  128/30013]\n",
      "loss: 0.054161  [12928/30013]\n",
      "loss: 0.041101  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 98.8%\n",
      "Done!\n",
      "Test Error: \n",
      " Accuracy: 98.2%, Avg loss: 0.053094 \n",
      "\n",
      "Test Error: \n",
      " Accuracy: 98.3%, Avg loss: 0.051196 \n",
      "\n",
      " Error: \n",
      " Accuracy: 98.3%  \n",
      "\n",
      "AUC value is: 0.49455462731081334\n",
      "Accuracy is: 0.49596666666666667\n",
      " Error: \n",
      " Accuracy: 98.3%  \n",
      "\n",
      "AUC value is: 0.4593615223867325\n",
      "Accuracy is: 0.51\n",
      "AUC value is: 0.49875063309873\n",
      "Accuracy is: 0.49978333333333336\n"
     ]
    }
   ],
   "source": [
    "# risk_bound_list = [0.01, 0.05, 0.1, 0.5, 1, 2, 4, 6, 10]\n",
    "risk_bound_list = [1]\n",
    "# k_init_list = [0, 0.2, 0.4, 0.5, 0.6, 0.8, 1]\n",
    "k_init_list = [0.5]\n",
    "model_test_correct = []\n",
    "average_lira_attack = []\n",
    "average_base_attack = []\n",
    "average_shadow_attack = []\n",
    "risk_base_attack = []\n",
    "risk_lira_attack = []\n",
    "risk_shadow_attack = []\n",
    "top_risk = 600\n",
    "for risk_bound in risk_bound_list: # 对隐私风险约束进行遍历\n",
    "    model_test_correct_t = []\n",
    "    average_lira_attack_t = []\n",
    "    average_base_attack_t = []\n",
    "    average_shadow_attack_t = []\n",
    "    risk_base_attack_t = []\n",
    "    risk_lira_attack_t = []\n",
    "    risk_shadow_attack_t = []\n",
    "    for k_init in k_init_list: # 对隐私风险约束进行遍历\n",
    "        y_soft = label_fix(risk_bound, k_init, y_onehot, conf_out_mean, pri_risk_all, mem_data)\n",
    "        x = X_data[mem_label]\n",
    "        y = y_onehot\n",
    "        # y = conf_out_mean\n",
    "        # y = y_soft\n",
    "        train_data = CustomDataset(x, y, model_transform)\n",
    "        train_dataloader = DataLoader(train_data, batch_size=batch_size)\n",
    "        TargetModel = globals()['create_{}_model'.format(model)](10, DATA_NAME)\n",
    "        TargetModel.to(device)\n",
    "        # loss_fn = nn.KLDivLoss()  # 使用KL散度损失\n",
    "        loss_fn = nn.CrossEntropyLoss()\n",
    "        optimizer = torch.optim.Adam(TargetModel.parameters(), lr=LEARNING_RATE)\n",
    "        for t in range(7):\n",
    "            print(f\"Epoch {t+1}\\n-------------------------------\")\n",
    "            # train_softlabel(train_dataloader, TargetModel, loss_fn, optimizer, device)\n",
    "            train_onehot(train_dataloader, TargetModel, loss_fn, optimizer, device)\n",
    "        print(\"Done!\")\n",
    "        # 训练完目标模型\n",
    "        loss_fn = nn.CrossEntropyLoss()\n",
    "        correct = evaluate(test_dataloader, TargetModel, loss_fn, device)\n",
    "        model_test_correct_t.append(correct)\n",
    "        # 执行基线攻击\n",
    "        pred_result = base_attack(all_dataloader, TargetModel, loss_fn, device)\n",
    "        accuracy = metrics.accuracy_score(train_keep[0], pred_result)\n",
    "        average_base_attack_t.append(accuracy)\n",
    "        pred_clip = pred_result[pri_risk_rank[:top_risk]]\n",
    "        mem_clip = train_keep[0][pri_risk_rank[:top_risk]]\n",
    "        accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "        risk_base_attack_t.append(accuracy)\n",
    "        # 执行似然比攻击\n",
    "        _, score = get_score_from_model(all_dataloader, TargetModel, device)\n",
    "        pred_result = LIRA_attack(train_keep, score_all, score, train_keep[0])\n",
    "        accuracy = evaluate_ROC(pred_result, train_keep[0], threshold=0)\n",
    "        average_lira_attack_t.append(accuracy)\n",
    "        pred_clip = pred_result[pri_risk_rank[:top_risk]]\n",
    "        mem_clip = train_keep[0][pri_risk_rank[:top_risk]]\n",
    "        pred_clip = pred_clip > 0\n",
    "        accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "        risk_lira_attack_t.append(accuracy)\n",
    "        # 执行影子模型攻击\n",
    "\n",
    "        # 提取数据集在模型上的置信度输出\n",
    "        targetX, _ = get_model_pred(all_dataloader, TargetModel, device)\n",
    "        targetX = targetX.detach().cpu().numpy()\n",
    "        targetX = targetX.astype(np.float32)\n",
    "        \n",
    "        top_k = 3\n",
    "        if top_k:\n",
    "            # 仅使用概率向量的前3个值\n",
    "            targetX, _ = get_top_k_conf(top_k, targetX, targetX)\n",
    "\n",
    "        shadow_attack_data = CustomDataset(targetX, train_keep[0], attack_transform)\n",
    "        shadow_attack_dataloader = DataLoader(shadow_attack_data, batch_size=batch_size, shuffle=False)\n",
    "        attack_test_scores, attack_test_mem = get_attack_pred(shadow_attack_dataloader, attack_model, device)\n",
    "        attack_test_scores, attack_test_mem = attack_test_scores.detach().cpu().numpy(), attack_test_mem.detach().cpu().numpy()\n",
    "        \n",
    "        pred_clip = attack_test_scores[pri_risk_rank[:top_risk]]\n",
    "        mem_clip = train_keep[0][pri_risk_rank[:top_risk]]\n",
    "        accuracy = evaluate_ROC(pred_clip, mem_clip)\n",
    "        risk_shadow_attack_t.append(accuracy)\n",
    "        \n",
    "        accuracy = evaluate_ROC(attack_test_scores, attack_test_mem)\n",
    "        average_shadow_attack_t.append(accuracy)\n",
    "    \n",
    "    \n",
    "    model_test_correct.append(model_test_correct_t)\n",
    "    average_lira_attack.append(average_lira_attack_t)\n",
    "    average_base_attack.append(average_base_attack_t)\n",
    "    average_shadow_attack.append(average_shadow_attack_t)\n",
    "    risk_base_attack.append(risk_base_attack_t)\n",
    "    risk_lira_attack.append(risk_lira_attack_t)\n",
    "    risk_shadow_attack.append(risk_shadow_attack_t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2e606bbe-03bf-45af-95f5-afec5c472459",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "8db5bc01-fca1-41ef-a92d-9df4b4174d0e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0.9825]]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_test_correct"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "2ca153f4-a88f-4029-99b2-3e3d2df4d36c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0.49596666666666667]]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "average_lira_attack"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "1804a241-e79b-4d1b-9ff2-049d8a9c6932",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0.5035166666666666]]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "average_base_attack"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "1fa82cb1-1b2c-45d5-bb0d-5d7088cd5e33",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0.49978333333333336]]"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "average_shadow_attack"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "af9f9e9a-687c-404d-8358-44ebce536e84",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0.5716666666666667]]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "risk_base_attack"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "f3909083-f0c5-42e3-a173-79c75cff965a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0.54]]"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "risk_lira_attack"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "8195b432-6a4d-4b2e-9fbf-c919c2559259",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0.51]]"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "risk_shadow_attack"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84b6bb0c-98cf-4120-9307-baea5b1fedc7",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "5af4222a-a780-41ef-93c5-2b7f2e06b087",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = pri_risk_all>0.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "3f25de29-c79d-4c23-9ad1-dd4bbd3b567d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6439"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "0e5d1389-3f8e-450c-b90f-1c1322ce026f",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1\n",
      "-------------------------------\n",
      "loss: 4.472650  [  128/30013]\n",
      "loss: 1.649380  [12928/30013]\n",
      "loss: 1.143343  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 48.6%\n",
      "Epoch 2\n",
      "-------------------------------\n",
      "loss: 1.070941  [  128/30013]\n",
      "loss: 0.810993  [12928/30013]\n",
      "loss: 0.626580  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 75.7%\n",
      "Epoch 3\n",
      "-------------------------------\n",
      "loss: 0.706174  [  128/30013]\n",
      "loss: 0.539391  [12928/30013]\n",
      "loss: 0.408337  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 83.9%\n",
      "Epoch 4\n",
      "-------------------------------\n",
      "loss: 0.505510  [  128/30013]\n",
      "loss: 0.387909  [12928/30013]\n",
      "loss: 0.319214  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 88.2%\n",
      "Epoch 5\n",
      "-------------------------------\n",
      "loss: 0.444639  [  128/30013]\n",
      "loss: 0.358504  [12928/30013]\n",
      "loss: 0.352953  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 89.8%\n",
      "Epoch 6\n",
      "-------------------------------\n",
      "loss: 0.333443  [  128/30013]\n",
      "loss: 0.260502  [12928/30013]\n",
      "loss: 0.281986  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 91.9%\n",
      "Epoch 7\n",
      "-------------------------------\n",
      "loss: 0.308637  [  128/30013]\n",
      "loss: 0.267112  [12928/30013]\n",
      "loss: 0.278607  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 93.3%\n",
      "Epoch 8\n",
      "-------------------------------\n",
      "loss: 0.294749  [  128/30013]\n",
      "loss: 0.261191  [12928/30013]\n",
      "loss: 0.217595  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 93.8%\n",
      "Epoch 9\n",
      "-------------------------------\n",
      "loss: 0.231464  [  128/30013]\n",
      "loss: 0.229771  [12928/30013]\n",
      "loss: 0.213772  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 94.6%\n",
      "Epoch 10\n",
      "-------------------------------\n",
      "loss: 0.251059  [  128/30013]\n",
      "loss: 0.201112  [12928/30013]\n",
      "loss: 0.202084  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 94.5%\n",
      "Epoch 11\n",
      "-------------------------------\n",
      "loss: 0.244840  [  128/30013]\n",
      "loss: 0.185513  [12928/30013]\n",
      "loss: 0.208201  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 94.6%\n",
      "Epoch 12\n",
      "-------------------------------\n",
      "loss: 0.259406  [  128/30013]\n",
      "loss: 0.188635  [12928/30013]\n",
      "loss: 0.216516  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 94.9%\n",
      "Epoch 13\n",
      "-------------------------------\n",
      "loss: 0.239766  [  128/30013]\n",
      "loss: 0.213542  [12928/30013]\n",
      "loss: 0.178580  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 95.2%\n",
      "Epoch 14\n",
      "-------------------------------\n",
      "loss: 0.301056  [  128/30013]\n",
      "loss: 0.186308  [12928/30013]\n",
      "loss: 0.204190  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 95.2%\n",
      "Epoch 15\n",
      "-------------------------------\n",
      "loss: 0.223059  [  128/30013]\n",
      "loss: 0.193320  [12928/30013]\n",
      "loss: 0.151275  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 95.0%\n",
      "Epoch 16\n",
      "-------------------------------\n",
      "loss: 0.216861  [  128/30013]\n",
      "loss: 0.223802  [12928/30013]\n",
      "loss: 0.199053  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 95.3%\n",
      "Epoch 17\n",
      "-------------------------------\n",
      "loss: 0.223872  [  128/30013]\n",
      "loss: 0.220534  [12928/30013]\n",
      "loss: 0.160955  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.0%\n",
      "Epoch 18\n",
      "-------------------------------\n",
      "loss: 0.201045  [  128/30013]\n",
      "loss: 0.170861  [12928/30013]\n",
      "loss: 0.177545  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.1%\n",
      "Epoch 19\n",
      "-------------------------------\n",
      "loss: 0.208667  [  128/30013]\n",
      "loss: 0.168011  [12928/30013]\n",
      "loss: 0.179155  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.0%\n",
      "Epoch 20\n",
      "-------------------------------\n",
      "loss: 0.197564  [  128/30013]\n",
      "loss: 0.218259  [12928/30013]\n",
      "loss: 0.200349  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.0%\n",
      "Epoch 21\n",
      "-------------------------------\n",
      "loss: 0.203598  [  128/30013]\n",
      "loss: 0.170179  [12928/30013]\n",
      "loss: 0.155913  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.1%\n",
      "Epoch 22\n",
      "-------------------------------\n",
      "loss: 0.203456  [  128/30013]\n",
      "loss: 0.182555  [12928/30013]\n",
      "loss: 0.188551  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.3%\n",
      "Epoch 23\n",
      "-------------------------------\n",
      "loss: 0.241357  [  128/30013]\n",
      "loss: 0.180865  [12928/30013]\n",
      "loss: 0.178108  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 95.9%\n",
      "Epoch 24\n",
      "-------------------------------\n",
      "loss: 0.213059  [  128/30013]\n",
      "loss: 0.181149  [12928/30013]\n",
      "loss: 0.179853  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 95.9%\n",
      "Epoch 25\n",
      "-------------------------------\n",
      "loss: 0.283138  [  128/30013]\n",
      "loss: 0.171364  [12928/30013]\n",
      "loss: 0.168471  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 95.9%\n",
      "Epoch 26\n",
      "-------------------------------\n",
      "loss: 0.241016  [  128/30013]\n",
      "loss: 0.174161  [12928/30013]\n",
      "loss: 0.183278  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.1%\n",
      "Epoch 27\n",
      "-------------------------------\n",
      "loss: 0.213600  [  128/30013]\n",
      "loss: 0.182009  [12928/30013]\n",
      "loss: 0.176108  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.1%\n",
      "Epoch 28\n",
      "-------------------------------\n",
      "loss: 0.203436  [  128/30013]\n",
      "loss: 0.204406  [12928/30013]\n",
      "loss: 0.165106  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 95.9%\n",
      "Epoch 29\n",
      "-------------------------------\n",
      "loss: 0.228872  [  128/30013]\n",
      "loss: 0.204502  [12928/30013]\n",
      "loss: 0.218465  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.0%\n",
      "Epoch 30\n",
      "-------------------------------\n",
      "loss: 0.236079  [  128/30013]\n",
      "loss: 0.164856  [12928/30013]\n",
      "loss: 0.170283  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.1%\n",
      "Epoch 31\n",
      "-------------------------------\n",
      "loss: 0.212307  [  128/30013]\n",
      "loss: 0.200149  [12928/30013]\n",
      "loss: 0.161398  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.2%\n",
      "Epoch 32\n",
      "-------------------------------\n",
      "loss: 0.211066  [  128/30013]\n",
      "loss: 0.173304  [12928/30013]\n",
      "loss: 0.222336  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.2%\n",
      "Epoch 33\n",
      "-------------------------------\n",
      "loss: 0.216000  [  128/30013]\n",
      "loss: 0.199875  [12928/30013]\n",
      "loss: 0.175452  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.2%\n",
      "Epoch 34\n",
      "-------------------------------\n",
      "loss: 0.214637  [  128/30013]\n",
      "loss: 0.191944  [12928/30013]\n",
      "loss: 0.149572  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.5%\n",
      "Epoch 35\n",
      "-------------------------------\n",
      "loss: 0.208708  [  128/30013]\n",
      "loss: 0.158448  [12928/30013]\n",
      "loss: 0.146900  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.4%\n",
      "Epoch 36\n",
      "-------------------------------\n",
      "loss: 0.211787  [  128/30013]\n",
      "loss: 0.173907  [12928/30013]\n",
      "loss: 0.180015  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.5%\n",
      "Epoch 37\n",
      "-------------------------------\n",
      "loss: 0.196892  [  128/30013]\n",
      "loss: 0.172144  [12928/30013]\n",
      "loss: 0.158901  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.6%\n",
      "Epoch 38\n",
      "-------------------------------\n",
      "loss: 0.210066  [  128/30013]\n",
      "loss: 0.173512  [12928/30013]\n",
      "loss: 0.161678  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.6%\n",
      "Epoch 39\n",
      "-------------------------------\n",
      "loss: 0.197919  [  128/30013]\n",
      "loss: 0.157836  [12928/30013]\n",
      "loss: 0.168123  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.6%\n",
      "Epoch 40\n",
      "-------------------------------\n",
      "loss: 0.196804  [  128/30013]\n",
      "loss: 0.160757  [12928/30013]\n",
      "loss: 0.167140  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.5%\n",
      "Epoch 41\n",
      "-------------------------------\n",
      "loss: 0.243621  [  128/30013]\n",
      "loss: 0.170321  [12928/30013]\n",
      "loss: 0.180636  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.5%\n",
      "Epoch 42\n",
      "-------------------------------\n",
      "loss: 0.210323  [  128/30013]\n",
      "loss: 0.190900  [12928/30013]\n",
      "loss: 0.178576  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.3%\n",
      "Epoch 43\n",
      "-------------------------------\n",
      "loss: 0.221697  [  128/30013]\n",
      "loss: 0.151081  [12928/30013]\n",
      "loss: 0.174978  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.3%\n",
      "Epoch 44\n",
      "-------------------------------\n",
      "loss: 0.206844  [  128/30013]\n",
      "loss: 0.158938  [12928/30013]\n",
      "loss: 0.162045  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.2%\n",
      "Epoch 45\n",
      "-------------------------------\n",
      "loss: 0.192235  [  128/30013]\n",
      "loss: 0.151613  [12928/30013]\n",
      "loss: 0.149540  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.4%\n",
      "Epoch 46\n",
      "-------------------------------\n",
      "loss: 0.214027  [  128/30013]\n",
      "loss: 0.200943  [12928/30013]\n",
      "loss: 0.156507  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.3%\n",
      "Epoch 47\n",
      "-------------------------------\n",
      "loss: 0.277381  [  128/30013]\n",
      "loss: 0.169996  [12928/30013]\n",
      "loss: 0.167048  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.6%\n",
      "Epoch 48\n",
      "-------------------------------\n",
      "loss: 0.213413  [  128/30013]\n",
      "loss: 0.169814  [12928/30013]\n",
      "loss: 0.194173  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.9%\n",
      "Epoch 49\n",
      "-------------------------------\n",
      "loss: 0.226828  [  128/30013]\n",
      "loss: 0.152970  [12928/30013]\n",
      "loss: 0.143832  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.9%\n",
      "Epoch 50\n",
      "-------------------------------\n",
      "loss: 0.208628  [  128/30013]\n",
      "loss: 0.148401  [12928/30013]\n",
      "loss: 0.147607  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.1%\n",
      "Epoch 51\n",
      "-------------------------------\n",
      "loss: 0.193201  [  128/30013]\n",
      "loss: 0.160364  [12928/30013]\n",
      "loss: 0.141227  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.8%\n",
      "Epoch 52\n",
      "-------------------------------\n",
      "loss: 0.185863  [  128/30013]\n",
      "loss: 0.161941  [12928/30013]\n",
      "loss: 0.154705  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.1%\n",
      "Epoch 53\n",
      "-------------------------------\n",
      "loss: 0.177853  [  128/30013]\n",
      "loss: 0.157332  [12928/30013]\n",
      "loss: 0.148602  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.1%\n",
      "Epoch 54\n",
      "-------------------------------\n",
      "loss: 0.182355  [  128/30013]\n",
      "loss: 0.179956  [12928/30013]\n",
      "loss: 0.157053  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.0%\n",
      "Epoch 55\n",
      "-------------------------------\n",
      "loss: 0.189756  [  128/30013]\n",
      "loss: 0.165668  [12928/30013]\n",
      "loss: 0.143113  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.1%\n",
      "Epoch 56\n",
      "-------------------------------\n",
      "loss: 0.183639  [  128/30013]\n",
      "loss: 0.166542  [12928/30013]\n",
      "loss: 0.141639  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.8%\n",
      "Epoch 57\n",
      "-------------------------------\n",
      "loss: 0.184578  [  128/30013]\n",
      "loss: 0.162722  [12928/30013]\n",
      "loss: 0.166730  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.8%\n",
      "Epoch 58\n",
      "-------------------------------\n",
      "loss: 0.180905  [  128/30013]\n",
      "loss: 0.161780  [12928/30013]\n",
      "loss: 0.143338  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.9%\n",
      "Epoch 59\n",
      "-------------------------------\n",
      "loss: 0.180179  [  128/30013]\n",
      "loss: 0.168216  [12928/30013]\n",
      "loss: 0.146162  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.0%\n",
      "Epoch 60\n",
      "-------------------------------\n",
      "loss: 0.231450  [  128/30013]\n",
      "loss: 0.163535  [12928/30013]\n",
      "loss: 0.154555  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.9%\n",
      "Epoch 61\n",
      "-------------------------------\n",
      "loss: 0.213555  [  128/30013]\n",
      "loss: 0.150797  [12928/30013]\n",
      "loss: 0.155503  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.0%\n",
      "Epoch 62\n",
      "-------------------------------\n",
      "loss: 0.181860  [  128/30013]\n",
      "loss: 0.147446  [12928/30013]\n",
      "loss: 0.164393  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.0%\n",
      "Epoch 63\n",
      "-------------------------------\n",
      "loss: 0.183488  [  128/30013]\n",
      "loss: 0.158162  [12928/30013]\n",
      "loss: 0.154454  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.7%\n",
      "Epoch 64\n",
      "-------------------------------\n",
      "loss: 0.181995  [  128/30013]\n",
      "loss: 0.156128  [12928/30013]\n",
      "loss: 0.143935  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.8%\n",
      "Epoch 65\n",
      "-------------------------------\n",
      "loss: 0.182866  [  128/30013]\n",
      "loss: 0.162697  [12928/30013]\n",
      "loss: 0.156329  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.9%\n",
      "Epoch 66\n",
      "-------------------------------\n",
      "loss: 0.192809  [  128/30013]\n",
      "loss: 0.157681  [12928/30013]\n",
      "loss: 0.144640  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.0%\n",
      "Epoch 67\n",
      "-------------------------------\n",
      "loss: 0.187103  [  128/30013]\n",
      "loss: 0.160625  [12928/30013]\n",
      "loss: 0.146527  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 96.9%\n",
      "Epoch 68\n",
      "-------------------------------\n",
      "loss: 0.188320  [  128/30013]\n",
      "loss: 0.151460  [12928/30013]\n",
      "loss: 0.147775  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.1%\n",
      "Epoch 69\n",
      "-------------------------------\n",
      "loss: 0.194118  [  128/30013]\n",
      "loss: 0.163950  [12928/30013]\n",
      "loss: 0.150863  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.2%\n",
      "Epoch 70\n",
      "-------------------------------\n",
      "loss: 0.186113  [  128/30013]\n",
      "loss: 0.145366  [12928/30013]\n",
      "loss: 0.139709  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.3%\n",
      "Epoch 71\n",
      "-------------------------------\n",
      "loss: 0.175825  [  128/30013]\n",
      "loss: 0.146421  [12928/30013]\n",
      "loss: 0.156065  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.1%\n",
      "Epoch 72\n",
      "-------------------------------\n",
      "loss: 0.179097  [  128/30013]\n",
      "loss: 0.153725  [12928/30013]\n",
      "loss: 0.140206  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.2%\n",
      "Epoch 73\n",
      "-------------------------------\n",
      "loss: 0.184573  [  128/30013]\n",
      "loss: 0.186953  [12928/30013]\n",
      "loss: 0.143776  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.0%\n",
      "Epoch 74\n",
      "-------------------------------\n",
      "loss: 0.177571  [  128/30013]\n",
      "loss: 0.152095  [12928/30013]\n",
      "loss: 0.152461  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.2%\n",
      "Epoch 75\n",
      "-------------------------------\n",
      "loss: 0.192808  [  128/30013]\n",
      "loss: 0.146985  [12928/30013]\n",
      "loss: 0.137803  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.3%\n",
      "Epoch 76\n",
      "-------------------------------\n",
      "loss: 0.179730  [  128/30013]\n",
      "loss: 0.156645  [12928/30013]\n",
      "loss: 0.139355  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.3%\n",
      "Epoch 77\n",
      "-------------------------------\n",
      "loss: 0.176289  [  128/30013]\n",
      "loss: 0.144789  [12928/30013]\n",
      "loss: 0.150190  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.4%\n",
      "Epoch 78\n",
      "-------------------------------\n",
      "loss: 0.171418  [  128/30013]\n",
      "loss: 0.137692  [12928/30013]\n",
      "loss: 0.161099  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.3%\n",
      "Epoch 79\n",
      "-------------------------------\n",
      "loss: 0.172981  [  128/30013]\n",
      "loss: 0.141878  [12928/30013]\n",
      "loss: 0.145939  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.3%\n",
      "Epoch 80\n",
      "-------------------------------\n",
      "loss: 0.177994  [  128/30013]\n",
      "loss: 0.142575  [12928/30013]\n",
      "loss: 0.136856  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.2%\n",
      "Epoch 81\n",
      "-------------------------------\n",
      "loss: 0.176384  [  128/30013]\n",
      "loss: 0.140367  [12928/30013]\n",
      "loss: 0.138742  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.2%\n",
      "Epoch 82\n",
      "-------------------------------\n",
      "loss: 0.175485  [  128/30013]\n",
      "loss: 0.145667  [12928/30013]\n",
      "loss: 0.171553  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.1%\n",
      "Epoch 83\n",
      "-------------------------------\n",
      "loss: 0.200769  [  128/30013]\n",
      "loss: 0.144866  [12928/30013]\n",
      "loss: 0.139596  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.0%\n",
      "Epoch 84\n",
      "-------------------------------\n",
      "loss: 0.188352  [  128/30013]\n",
      "loss: 0.159034  [12928/30013]\n",
      "loss: 0.146437  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.2%\n",
      "Epoch 85\n",
      "-------------------------------\n",
      "loss: 0.176003  [  128/30013]\n",
      "loss: 0.149853  [12928/30013]\n",
      "loss: 0.142023  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.4%\n",
      "Epoch 86\n",
      "-------------------------------\n",
      "loss: 0.172271  [  128/30013]\n",
      "loss: 0.158639  [12928/30013]\n",
      "loss: 0.136383  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.6%\n",
      "Epoch 87\n",
      "-------------------------------\n",
      "loss: 0.178108  [  128/30013]\n",
      "loss: 0.147153  [12928/30013]\n",
      "loss: 0.140914  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.6%\n",
      "Epoch 88\n",
      "-------------------------------\n",
      "loss: 0.174955  [  128/30013]\n",
      "loss: 0.143922  [12928/30013]\n",
      "loss: 0.135247  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.7%\n",
      "Epoch 89\n",
      "-------------------------------\n",
      "loss: 0.173619  [  128/30013]\n",
      "loss: 0.140865  [12928/30013]\n",
      "loss: 0.138878  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.5%\n",
      "Epoch 90\n",
      "-------------------------------\n",
      "loss: 0.175317  [  128/30013]\n",
      "loss: 0.139972  [12928/30013]\n",
      "loss: 0.137187  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.6%\n",
      "Epoch 91\n",
      "-------------------------------\n",
      "loss: 0.172395  [  128/30013]\n",
      "loss: 0.136255  [12928/30013]\n",
      "loss: 0.138954  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.7%\n",
      "Epoch 92\n",
      "-------------------------------\n",
      "loss: 0.169050  [  128/30013]\n",
      "loss: 0.133029  [12928/30013]\n",
      "loss: 0.147321  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.5%\n",
      "Epoch 93\n",
      "-------------------------------\n",
      "loss: 0.173723  [  128/30013]\n",
      "loss: 0.140271  [12928/30013]\n",
      "loss: 0.142930  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.4%\n",
      "Epoch 94\n",
      "-------------------------------\n",
      "loss: 0.174549  [  128/30013]\n",
      "loss: 0.152539  [12928/30013]\n",
      "loss: 0.167622  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.3%\n",
      "Epoch 95\n",
      "-------------------------------\n",
      "loss: 0.213162  [  128/30013]\n",
      "loss: 0.141026  [12928/30013]\n",
      "loss: 0.145228  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.2%\n",
      "Epoch 96\n",
      "-------------------------------\n",
      "loss: 0.184389  [  128/30013]\n",
      "loss: 0.144376  [12928/30013]\n",
      "loss: 0.145684  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.1%\n",
      "Epoch 97\n",
      "-------------------------------\n",
      "loss: 0.168461  [  128/30013]\n",
      "loss: 0.145178  [12928/30013]\n",
      "loss: 0.139375  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.5%\n",
      "Epoch 98\n",
      "-------------------------------\n",
      "loss: 0.179677  [  128/30013]\n",
      "loss: 0.140203  [12928/30013]\n",
      "loss: 0.137043  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.5%\n",
      "Epoch 99\n",
      "-------------------------------\n",
      "loss: 0.168118  [  128/30013]\n",
      "loss: 0.141010  [12928/30013]\n",
      "loss: 0.139320  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.5%\n",
      "Epoch 100\n",
      "-------------------------------\n",
      "loss: 0.167739  [  128/30013]\n",
      "loss: 0.139121  [12928/30013]\n",
      "loss: 0.131340  [25728/30013]\n",
      "Train Error: \n",
      " Accuracy: 97.9%\n",
      "Done!\n"
     ]
    }
   ],
   "source": [
    "dis_train = mem_data[dist_keep[0]]\n",
    "x = X_data[mem_label]\n",
    "y = y_onehot\n",
    "train_data = CustomDataset(x, y, model_transform)\n",
    "train_dataloader = DataLoader(train_data, batch_size=batch_size)\n",
    "TargetModel = globals()['create_{}_model'.format(model)](x.shape[1], 100)\n",
    "TargetModel.to(device)\n",
    "loss_fn = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(TargetModel.parameters(), lr=LEARNING_RATE)\n",
    "for t in range(epochs):\n",
    "    print(f\"Epoch {t+1}\\n-------------------------------\")\n",
    "    train_onehot(train_dataloader, TargetModel, loss_fn, optimizer, device)\n",
    "print(\"Done!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b08b69dd-34ab-4d9b-a953-a7c4557cb42a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "6ee709f5-8967-47d3-984a-89d443c7dba4",
   "metadata": {},
   "outputs": [],
   "source": [
    "dataframe = pd.read_csv('../datasets/purchase100.txt', sep=',', encoding='utf-8', header=None)\n",
    "X_tmp = dataframe.iloc[:, range(600)].values\n",
    "Y_tmp = np.array([i for i in dataframe.loc[:, 600]])\n",
    "\n",
    "x_test_data = X_tmp[90000:110000]\n",
    "y_test_data = Y_tmp[90000:110000]\n",
    "test_data = CustomDataset(x_test_data, y_test_data, model_transform)\n",
    "test_dataloader = DataLoader(test_data, batch_size=batch_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "d7ef4969-de10-4972-b2cc-6c160e4c3888",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Error: \n",
      " Accuracy: 83.6%, Avg loss: 0.473724 \n",
      "\n"
     ]
    }
   ],
   "source": [
    "evaluate(test_dataloader, TargetModel, loss_fn, device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b08eee75-1667-4467-adcf-211a35147c40",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "fd49e0e6-3093-47b5-8b5d-e34970bced1b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "M_CNN(\n",
       "  (conv1): Conv2d(1, 16, kernel_size=(8, 8), stride=(2, 2), padding=(3, 3))\n",
       "  (conv2): Conv2d(16, 32, kernel_size=(4, 4), stride=(2, 2))\n",
       "  (fc1): Linear(in_features=512, out_features=32, bias=True)\n",
       "  (fc2): Linear(in_features=32, out_features=10, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "CompareModel = globals()['create_{}_model'.format(model)](10, DATA_NAME)\n",
    "weight_path = os.path.join(weight_dir, \"{}_{}_epoch{}_model{}.pth\".format(data_name, model, epochs, 0))\n",
    "# print(Reference_Model)\n",
    "CompareModel.load_state_dict(torch.load(weight_path))\n",
    "CompareModel.to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "1c3b06ae-53b3-44a4-840d-51b978c3caa2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Error: \n",
      " Accuracy: 98.5%, Avg loss: 0.122318 \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.9849"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "evaluate(test_dataloader, CompareModel, loss_fn, device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9a15990e-2f5d-4c1f-abf3-6f9ff53d4da1",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "390cd75e-7d82-4bc6-97ed-de74015a3910",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 尝试用基线攻击测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "74be44ec-2b61-4221-88ae-c210b237df1f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Error: \n",
      " Accuracy: 88.5%, Avg loss: 0.318909 \n",
      "\n",
      "0.5392\n"
     ]
    }
   ],
   "source": [
    "loss_fn = nn.CrossEntropyLoss()\n",
    "pred_result = base_attack(all_dataloader, TargetModel, loss_fn, device)\n",
    "\n",
    "pred_clip = pred_result[pri_risk_rank[:5000]]\n",
    "mem_clip = train_keep[0][pri_risk_rank[:5000]]\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "aa548896-635c-475d-8b08-6604046639dd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Error: \n",
      " Accuracy: 93.2%, Avg loss: 0.406874 \n",
      "\n",
      "0.8634\n"
     ]
    }
   ],
   "source": [
    "loss_fn = nn.CrossEntropyLoss()\n",
    "pred_result = base_attack(all_dataloader, CompareModel, loss_fn, device)\n",
    "\n",
    "pred_clip = pred_result[pri_risk_rank[:5000]]\n",
    "mem_clip = train_keep[0][pri_risk_rank[:5000]]\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "7cc63313-daa2-41ae-9d19-66694569c13b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 尝试用LIRA攻击测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "b20b9720-0f13-4930-a526-9340055ce185",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AUC value is: 0.5704715637885492\n",
      "Accuracy is: 0.5523833333333333\n",
      "0.8333333333333334\n"
     ]
    }
   ],
   "source": [
    "pred_result = LIRA_attack(train_keep, score_all, score_all[0], train_keep[0])\n",
    "evaluate_ROC(pred_result, train_keep[0], threshold=0)\n",
    "\n",
    "pred_clip = pred_result[pri_risk_rank[:600]]\n",
    "mem_clip = train_keep[0][pri_risk_rank[:600]]\n",
    "pred_clip = pred_clip > 0\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "e4d6376a-15a3-4b28-b027-7f5fa3cf6669",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " Error: \n",
      " Accuracy: 88.5%  \n",
      "\n",
      "AUC value is: 0.5525037548590384\n",
      "Accuracy is: 0.49088333333333334\n",
      "0.4992\n"
     ]
    }
   ],
   "source": [
    "_, score = get_score_from_model(all_dataloader, TargetModel, device)\n",
    "pred_result = LIRA_attack(train_keep, score_all, score, train_keep[0])\n",
    "evaluate_ROC(pred_result, train_keep[0], threshold=0)\n",
    "\n",
    "pred_clip = pred_result[pri_risk_rank[:5000]]\n",
    "mem_clip = train_keep[0][pri_risk_rank[:5000]]\n",
    "pred_clip = pred_clip > 0\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "103a6b29-9b67-4a2f-9be1-08f421fc9a7d",
   "metadata": {},
   "outputs": [],
   "source": [
    "auc_value = metrics.roc_auc_score(train_keep[0], pred_result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "96b0859c-83af-42b3-ad58-4aa84cfbe894",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ROC_plot(pred_result, train_keep[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "373e013e-6d50-41da-ad7c-ed9ecdb61370",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1bb563f4-61eb-4e94-8a4a-31618dba7f6e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7e97378d-80d7-490d-a058-a095fb5d2d21",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f546eadd-f1bf-4086-b8f0-6b8e7681cb26",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2938b89e-f0f7-49b1-ac3d-94a44492171c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d573cd06-c4df-4b78-bf08-61e29e6d7fe6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2158bca8-7015-4b57-bcf3-6a5fe1a84cd3",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "8bf4ae41-482b-464b-b2df-f79924f00fe2",
   "metadata": {},
   "source": [
    "## 脆弱点的两种提取方式"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a20f6954-5154-483b-a64b-8ab536b4989b",
   "metadata": {},
   "source": [
    "### 风险指标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "90586eba-a7f4-4a19-a8a8-54d5d8633693",
   "metadata": {},
   "outputs": [],
   "source": [
    "# # 加载所有参考模型上的损失、置信度、得分输出\n",
    "# conf_data_all, label_data, score_all = load_score_data_all(X_data, Y_data, weight_dir, num_shadowsets, data_name, model, weight_part, model_transform, batch_size, device)\n",
    "# loss_fn = nn.CrossEntropyLoss(reduction='none')\n",
    "# loss_data_all, label_data = load_loss_data_all(X_data, Y_data, loss_fn, weight_dir, num_shadowsets, data_name, model, weight_part, model_transform, batch_size, device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5fbe2bf6-1750-4c23-91a8-80caf9b0825e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# np.save('../outputs_save/Purchase100_limited_loss.npy', loss_data_all)\n",
    "# np.save('../outputs_save/Purchase100_limited_score.npy', score_all)\n",
    "# np.save('../outputs_save/Purchase100_limited_conf.npy', conf_data_all)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "5a6e9c56-60bd-4bfc-a912-5e3b5eb52a4e",
   "metadata": {},
   "outputs": [],
   "source": [
    "loss_data_all = np.load('../outputs_save/Purchase100_limited_loss.npy')\n",
    "score_all = np.load('../outputs_save/Purchase100_limited_score.npy')\n",
    "conf_data_all = np.load('../outputs_save/Purchase100_limited_conf.npy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "8b45bd6b-c391-4ced-99bd-57b0b8c3c30b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 为每个数据点计算风险指标\n",
    "# 计算出一个点的脆弱程度评分\n",
    "pri_risk_all = get_risk_score(loss_data_all, train_keep)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "d8258b9c-d6f3-4e64-ab4f-4b068bb4b209",
   "metadata": {},
   "outputs": [],
   "source": [
    "pri_risk_rank = np.argsort(pri_risk_all)\n",
    "pri_risk_rank = np.flip(pri_risk_rank)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16cc7233-a9a0-4e74-990d-70e0e6ebfb74",
   "metadata": {},
   "source": [
    "### 离群点"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "e7e42cbf-89f1-4d1f-bbd0-dc87252c22cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 准备好logits的输出\n",
    "# 计算余弦相似度 5w*5w的大型矩阵\n",
    "# 邻居距离alpha，邻居数量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "8d4c50e3-0ca3-463c-ad2a-4e4fd987b12e",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# logits_data_all, label_data = load_logits_data_all(X_data, Y_data, weight_dir, num_shadowsets, data_name, model, weight_part, model_transform, batch_size, device)\n",
    "# np.save('../outputs_save/Purchase100_limited_logits.npy', logits_data_all)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a9314bc7-f529-46f5-834b-d1c387effef7",
   "metadata": {},
   "outputs": [],
   "source": [
    "logits_data_all = np.load('../outputs_save/Purchase100_limited_logits.npy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "50d2365f-9e9d-4ffc-a9f7-16c1d3ed5646",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 按照k个模型进行拼接\n",
    "k = 10\n",
    "for i in range(k):\n",
    "    if i == 0:\n",
    "        combine_features = logits_data_all[i]\n",
    "    else:\n",
    "        combine_features = np.concatenate((combine_features, logits_data_all[i]),axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "1308ab27-3798-4a3c-8dd2-b5ce0234042e",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "compute to: 0\n",
      "compute to: 50\n",
      "compute to: 100\n",
      "compute to: 150\n",
      "compute to: 200\n",
      "compute to: 250\n",
      "compute to: 300\n",
      "compute to: 350\n",
      "compute to: 400\n",
      "compute to: 450\n",
      "compute to: 500\n",
      "compute to: 550\n",
      "compute to: 600\n",
      "compute to: 650\n",
      "compute to: 700\n",
      "compute to: 750\n",
      "compute to: 800\n",
      "compute to: 850\n",
      "compute to: 900\n",
      "compute to: 950\n",
      "compute to: 1000\n",
      "compute to: 1050\n",
      "compute to: 1100\n",
      "compute to: 1150\n",
      "compute to: 1200\n",
      "compute to: 1250\n",
      "compute to: 1300\n",
      "compute to: 1350\n",
      "compute to: 1400\n",
      "compute to: 1450\n",
      "compute to: 1500\n",
      "compute to: 1550\n",
      "compute to: 1600\n",
      "compute to: 1650\n",
      "compute to: 1700\n",
      "compute to: 1750\n",
      "compute to: 1800\n",
      "compute to: 1850\n",
      "compute to: 1900\n",
      "compute to: 1950\n",
      "compute to: 2000\n",
      "compute to: 2050\n",
      "compute to: 2100\n",
      "compute to: 2150\n",
      "compute to: 2200\n",
      "compute to: 2250\n",
      "compute to: 2300\n",
      "compute to: 2350\n",
      "compute to: 2400\n",
      "compute to: 2450\n",
      "compute to: 2500\n",
      "compute to: 2550\n",
      "compute to: 2600\n",
      "compute to: 2650\n",
      "compute to: 2700\n",
      "compute to: 2750\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[19], line 13\u001b[0m\n\u001b[1;32m     11\u001b[0m vec1 \u001b[38;5;241m=\u001b[39m combine_features[i]\n\u001b[1;32m     12\u001b[0m vec2 \u001b[38;5;241m=\u001b[39m combine_features[j]        \n\u001b[0;32m---> 13\u001b[0m cos_sim \u001b[38;5;241m=\u001b[39m vec1\u001b[38;5;241m.\u001b[39mdot(vec2) \u001b[38;5;241m/\u001b[39m (np\u001b[38;5;241m.\u001b[39mlinalg\u001b[38;5;241m.\u001b[39mnorm(vec1) \u001b[38;5;241m*\u001b[39m \u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlinalg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mnorm\u001b[49m\u001b[43m(\u001b[49m\u001b[43mvec2\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[1;32m     14\u001b[0m cos_dis \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.5\u001b[39m \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m0.5\u001b[39m \u001b[38;5;241m*\u001b[39m cos_sim\n\u001b[1;32m     15\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m m \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;28mlen\u001b[39m(alpha_list)):\n",
      "File \u001b[0;32m<__array_function__ internals>:200\u001b[0m, in \u001b[0;36mnorm\u001b[0;34m(*args, **kwargs)\u001b[0m\n",
      "File \u001b[0;32m~/.conda/envs/opacus/lib/python3.8/site-packages/numpy/linalg/linalg.py:2342\u001b[0m, in \u001b[0;36mnorm\u001b[0;34m(x, ord, axis, keepdims)\u001b[0m\n\u001b[1;32m   2338\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_norm_dispatcher\u001b[39m(x, \u001b[38;5;28mord\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, axis\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, keepdims\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m):\n\u001b[1;32m   2339\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m (x,)\n\u001b[0;32m-> 2342\u001b[0m \u001b[38;5;129m@array_function_dispatch\u001b[39m(_norm_dispatcher)\n\u001b[1;32m   2343\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mnorm\u001b[39m(x, \u001b[38;5;28mord\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, axis\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, keepdims\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m):\n\u001b[1;32m   2344\u001b[0m \u001b[38;5;250m    \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m   2345\u001b[0m \u001b[38;5;124;03m    Matrix or vector norm.\u001b[39;00m\n\u001b[1;32m   2346\u001b[0m \n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m   2491\u001b[0m \n\u001b[1;32m   2492\u001b[0m \u001b[38;5;124;03m    \"\"\"\u001b[39;00m\n\u001b[1;32m   2493\u001b[0m     x \u001b[38;5;241m=\u001b[39m asarray(x)\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "# 数据量太大，不能保存所有的余弦相似度，只能需要时计算\n",
    "alpha_list = [0.05, 0.1, 0.12, 0.15, 0.2, 0.3]\n",
    "n_num_list = []\n",
    "# for i in range(combine_features.shape[0]):\n",
    "for i in range(10000):\n",
    "    n_count = [0 for _ in alpha_list]\n",
    "    if i%50 == 0:\n",
    "        print(f\"compute to: {i}\")\n",
    "    for j in range(combine_features.shape[0]):\n",
    "        # 余弦距离的计算\n",
    "        vec1 = combine_features[i]\n",
    "        vec2 = combine_features[j]        \n",
    "        cos_sim = vec1.dot(vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))\n",
    "        cos_dis = 0.5 - 0.5 * cos_sim\n",
    "        for m in range(len(alpha_list)):\n",
    "            if (cos_dis < alpha_list[m]):\n",
    "                n_count[m] += 1\n",
    "    n_num_list.append(n_count)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "ae886e98-bf25-4c0d-a2fa-f2c948574aa8",
   "metadata": {},
   "outputs": [
    {
     "ename": "FileNotFoundError",
     "evalue": "[Errno 2] No such file or directory: '../outputs_save/Purchase100_limited_neigh.npy'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mFileNotFoundError\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[20], line 3\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;66;03m# neigh_data_all = np.array(n_num_list)\u001b[39;00m\n\u001b[1;32m      2\u001b[0m \u001b[38;5;66;03m# np.save('CIFAR10_neigh.npy', neigh_data_all)\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m neigh_data_all \u001b[38;5;241m=\u001b[39m \u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m../outputs_save/Purchase100_limited_neigh.npy\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/.conda/envs/opacus/lib/python3.8/site-packages/numpy/lib/npyio.py:405\u001b[0m, in \u001b[0;36mload\u001b[0;34m(file, mmap_mode, allow_pickle, fix_imports, encoding, max_header_size)\u001b[0m\n\u001b[1;32m    403\u001b[0m     own_fid \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m    404\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 405\u001b[0m     fid \u001b[38;5;241m=\u001b[39m stack\u001b[38;5;241m.\u001b[39menter_context(\u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mos_fspath\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfile\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mrb\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m)\n\u001b[1;32m    406\u001b[0m     own_fid \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m    408\u001b[0m \u001b[38;5;66;03m# Code to distinguish from NumPy binary files and pickles.\u001b[39;00m\n",
      "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '../outputs_save/Purchase100_limited_neigh.npy'"
     ]
    }
   ],
   "source": [
    "neigh_data_all = np.array(n_num_list)\n",
    "np.save('../outputs_save/Purchase100_limited_neigh.npy', neigh_data_all)\n",
    "neigh_data_all = np.load('../outputs_save/Purchase100_limited_neigh.npy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "79592536-1181-4647-9e40-fc959daa668e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(50000, 6)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "neigh_data_all.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "9d815b0b-568b-46d5-bdeb-fba567a8e213",
   "metadata": {},
   "outputs": [],
   "source": [
    "neigh_num = neigh_data_all[:,1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "7bc974ea-ffb5-432f-b9da-ab7abce10270",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(50000,)"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "neigh_num.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "ddd4b8fa-1653-4bab-bf8f-4e2a116b17b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "risk_rank = np.argsort(neigh_num)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "789a839a-cb2b-4da7-a1a2-ecac971344ef",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([29631, 39852, 26325, ..., 47315, 41363, 17410])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "risk_rank"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cce6c5e2-b030-4874-b08e-bf8466815484",
   "metadata": {},
   "source": [
    "## 针对脆弱点展开攻击"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14cb98e0-737b-4ed0-93bd-a52681974606",
   "metadata": {},
   "source": [
    "### 基线攻击"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "8c66acdc-645a-4cf8-b0f6-babc51bce18a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 预测正确的判断为成员，预测不正确的判断为非成员"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "ecc0a131-e71a-4cd1-b5a3-a6c750abc382",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "CNN(\n",
       "  (conv1): Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (conv2): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (conv3): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
       "  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
       "  (fc1): Linear(in_features=1024, out_features=500, bias=True)\n",
       "  (fc2): Linear(in_features=500, out_features=10, bias=True)\n",
       "  (BatchNorm1): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (BatchNorm2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (BatchNorm3): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       ")"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建对应的目标模型\n",
    "if model in ['NN', 'NN_4layer']:\n",
    "    Target_Model = globals()['create_{}_model'.format(model)](X_data.shape[1], Y_data.max()+1)\n",
    "elif model == 'CNN':\n",
    "    Target_Model = globals()['create_{}_model'.format(model)](Y_data.max()+1, data_name)\n",
    "# 加载参数\n",
    "weight_path = os.path.join(weight_dir, \"{}_{}_epoch{}_model{}.pth\".format(data_name, model, epochs, tar_model))\n",
    "# print(Reference_Model)\n",
    "Target_Model.load_state_dict(torch.load(weight_path))\n",
    "Target_Model.to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "670ebafe-5710-4b0c-b05d-008a6098dbc8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Error: \n",
      " Accuracy: 84.7%, Avg loss: 1.124064 \n",
      "\n"
     ]
    }
   ],
   "source": [
    "loss_fn = nn.CrossEntropyLoss()\n",
    "pred_result = base_attack(train_dataloader, Target_Model, loss_fn, device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "d0dfd319-c536-4a57-a2b9-246f9a577f60",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.8\n",
      "0.916\n"
     ]
    }
   ],
   "source": [
    "pred_clip = pred_result[risk_rank[:5000]]\n",
    "mem_clip = train_keep[0][risk_rank[:5000]]\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)\n",
    "\n",
    "pred_clip = pred_result[pri_risk_rank[:5000]]\n",
    "mem_clip = train_keep[0][pri_risk_rank[:5000]]\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c08b9a40-068e-4411-8a51-13a05337a7cd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "5cf3f668-0b0b-41b1-bc5f-73f89bed9169",
   "metadata": {},
   "source": [
    "### 阈值攻击"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "61729130-6c97-4a19-b7c5-767f6ba1ae70",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 基于损失的阈值去做攻击，阈值如何确定？两个均值的均值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "0dd9f430-c918-47cd-9e8d-4ee1b35bf143",
   "metadata": {},
   "outputs": [],
   "source": [
    "loss_threshold = get_loss_threshold(loss_data_all, train_keep)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "18f8fd0e-f86a-47fc-8105-7a3a53b10b28",
   "metadata": {},
   "outputs": [],
   "source": [
    "target_loss = loss_data_all[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "09270911-4d24-4c91-9c59-224213d1c319",
   "metadata": {},
   "outputs": [],
   "source": [
    "pred_result = target_loss < loss_threshold"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "ef57e35b-e721-4cea-ad31-6b7cc4ef5362",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.7938\n",
      "0.8614\n"
     ]
    }
   ],
   "source": [
    "pred_clip = pred_result[risk_rank[:5000]]\n",
    "mem_clip = train_keep[0][risk_rank[:5000]]\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)\n",
    "\n",
    "pred_clip = pred_result[pri_risk_rank[:5000]]\n",
    "mem_clip = train_keep[0][pri_risk_rank[:5000]]\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "736cdbcb-9dd3-45ab-bcc4-37c7f490a588",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8259bc0c-fbc1-4025-bf4a-b194236a39ff",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "786da5f1-1ae9-4f9b-ae7f-e18702ea84a7",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "77876b58-669a-483a-b80c-8b041486eda0",
   "metadata": {},
   "source": [
    "### 似然比攻击"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "f1304cdd-cd2c-437f-af20-bdd3eb68caab",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先对所有目标数据执行攻击，然后根据脆弱点筛选获取对应的攻击成功率或者ROC\n",
    "# 输出两个，memlabel和pred_result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "c9ed8ba5-393b-4bdd-8a65-bbd6bbcaf4b6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AUC value is: 0.7769893964732137\n",
      "Accuracy is: 0.69174\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.69174"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pred_result = LIRA_attack(train_keep, score_all, score_all[0], train_keep[0])\n",
    "evaluate_ROC(pred_result, train_keep[0], threshold=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "5fdb2095-a077-40a4-b954-c4947b015080",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.8458\n",
      "0.9234\n"
     ]
    }
   ],
   "source": [
    "pred_clip = pred_result[risk_rank[:5000]]\n",
    "mem_clip = train_keep[0][risk_rank[:5000]]\n",
    "pred_clip = pred_clip > 0\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)\n",
    "\n",
    "pred_clip = pred_result[pri_risk_rank[:5000]]\n",
    "mem_clip = train_keep[0][pri_risk_rank[:5000]]\n",
    "pred_clip = pred_clip > 0\n",
    "accuracy = metrics.accuracy_score(mem_clip, pred_clip)\n",
    "print(accuracy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "35c96a5b-843d-4cb6-b964-f13dadac3193",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "26be2f5a-29e3-45c7-b6f0-c5382828f63f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "457be14e-4b30-488a-aab0-0ae0b345e27e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "8ea3f420-9a04-420f-83b6-06ea1658f6c7",
   "metadata": {},
   "source": [
    "### 影子模型攻击"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "7c5e0038-e2b6-4997-a64f-c9e80ed2c9c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在所有数据上执行一次攻击"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "7d7fefb0-3e20-40e2-be99-4527c0f62306",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n",
      " Error: \n",
      " Accuracy: 98.2%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 70.7%  \n",
      "\n",
      "(50000, 10) (50000,) (50000,)\n",
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n",
      " Error: \n",
      " Accuracy: 98.4%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 70.9%  \n",
      "\n",
      "(50000, 10) (50000,) (50000,)\n",
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n",
      " Error: \n",
      " Accuracy: 97.3%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 70.7%  \n",
      "\n",
      "(50000, 10) (50000,) (50000,)\n",
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n",
      " Error: \n",
      " Accuracy: 98.5%  \n",
      "\n",
      " Error: \n",
      " Accuracy: 70.9%  \n",
      "\n",
      "test data: (50000, 10) (50000,) (50000,)\n",
      "(150000, 10) (150000,)\n",
      "Attack_NN(\n",
      "  (linear_relu_stack): Sequential(\n",
      "    (0): Linear(in_features=11, out_features=128, bias=True)\n",
      "    (1): ReLU()\n",
      "    (2): Linear(in_features=128, out_features=64, bias=True)\n",
      "    (3): ReLU()\n",
      "    (4): Linear(in_features=64, out_features=1, bias=True)\n",
      "  )\n",
      ")\n",
      "Epoch 1\n",
      "-------------------------------\n",
      "loss: 0.697296  [   64/150000]\n",
      "loss: 0.691852  [ 6464/150000]\n",
      "loss: 0.687517  [12864/150000]\n",
      "loss: 0.651151  [19264/150000]\n",
      "loss: 0.638183  [25664/150000]\n",
      "loss: 0.665337  [32064/150000]\n",
      "loss: 0.629165  [38464/150000]\n",
      "loss: 0.629897  [44864/150000]\n",
      "loss: 0.633173  [51264/150000]\n",
      "loss: 0.613899  [57664/150000]\n",
      "loss: 0.603700  [64064/150000]\n",
      "loss: 0.624719  [70464/150000]\n",
      "loss: 0.607570  [76864/150000]\n",
      "loss: 0.615966  [83264/150000]\n",
      "loss: 0.594782  [89664/150000]\n",
      "loss: 0.612963  [96064/150000]\n",
      "loss: 0.666927  [102464/150000]\n",
      "loss: 0.635343  [108864/150000]\n",
      "loss: 0.551613  [115264/150000]\n",
      "loss: 0.614503  [121664/150000]\n",
      "loss: 0.609472  [128064/150000]\n",
      "loss: 0.651940  [134464/150000]\n",
      "loss: 0.623228  [140864/150000]\n",
      "loss: 0.632289  [147264/150000]\n",
      "Epoch 2\n",
      "-------------------------------\n",
      "loss: 0.597696  [   64/150000]\n",
      "loss: 0.666137  [ 6464/150000]\n",
      "loss: 0.574050  [12864/150000]\n",
      "loss: 0.663844  [19264/150000]\n",
      "loss: 0.615269  [25664/150000]\n",
      "loss: 0.637435  [32064/150000]\n",
      "loss: 0.607537  [38464/150000]\n",
      "loss: 0.640098  [44864/150000]\n",
      "loss: 0.555198  [51264/150000]\n",
      "loss: 0.508200  [57664/150000]\n",
      "loss: 0.649726  [64064/150000]\n",
      "loss: 0.579738  [70464/150000]\n",
      "loss: 0.639545  [76864/150000]\n",
      "loss: 0.595912  [83264/150000]\n",
      "loss: 0.603856  [89664/150000]\n",
      "loss: 0.624075  [96064/150000]\n",
      "loss: 0.644577  [102464/150000]\n",
      "loss: 0.573552  [108864/150000]\n",
      "loss: 0.593017  [115264/150000]\n",
      "loss: 0.678881  [121664/150000]\n",
      "loss: 0.645067  [128064/150000]\n",
      "loss: 0.678110  [134464/150000]\n",
      "loss: 0.592467  [140864/150000]\n",
      "loss: 0.644923  [147264/150000]\n",
      "Epoch 3\n",
      "-------------------------------\n",
      "loss: 0.549876  [   64/150000]\n",
      "loss: 0.540238  [ 6464/150000]\n",
      "loss: 0.602370  [12864/150000]\n",
      "loss: 0.577029  [19264/150000]\n",
      "loss: 0.573094  [25664/150000]\n",
      "loss: 0.556609  [32064/150000]\n",
      "loss: 0.588493  [38464/150000]\n",
      "loss: 0.620299  [44864/150000]\n",
      "loss: 0.532603  [51264/150000]\n",
      "loss: 0.550144  [57664/150000]\n",
      "loss: 0.655471  [64064/150000]\n",
      "loss: 0.557127  [70464/150000]\n",
      "loss: 0.562649  [76864/150000]\n",
      "loss: 0.611032  [83264/150000]\n",
      "loss: 0.609907  [89664/150000]\n",
      "loss: 0.641321  [96064/150000]\n",
      "loss: 0.517016  [102464/150000]\n",
      "loss: 0.548020  [108864/150000]\n",
      "loss: 0.606035  [115264/150000]\n",
      "loss: 0.712533  [121664/150000]\n",
      "loss: 0.600617  [128064/150000]\n",
      "loss: 0.581069  [134464/150000]\n",
      "loss: 0.684818  [140864/150000]\n",
      "loss: 0.590795  [147264/150000]\n",
      "Epoch 4\n",
      "-------------------------------\n",
      "loss: 0.614286  [   64/150000]\n",
      "loss: 0.603604  [ 6464/150000]\n",
      "loss: 0.656957  [12864/150000]\n",
      "loss: 0.724023  [19264/150000]\n",
      "loss: 0.610916  [25664/150000]\n",
      "loss: 0.620281  [32064/150000]\n",
      "loss: 0.583793  [38464/150000]\n",
      "loss: 0.590866  [44864/150000]\n",
      "loss: 0.590776  [51264/150000]\n",
      "loss: 0.535479  [57664/150000]\n",
      "loss: 0.576726  [64064/150000]\n",
      "loss: 0.629341  [70464/150000]\n",
      "loss: 0.564287  [76864/150000]\n",
      "loss: 0.611278  [83264/150000]\n",
      "loss: 0.531345  [89664/150000]\n",
      "loss: 0.570144  [96064/150000]\n",
      "loss: 0.544331  [102464/150000]\n",
      "loss: 0.641698  [108864/150000]\n",
      "loss: 0.555752  [115264/150000]\n",
      "loss: 0.562733  [121664/150000]\n",
      "loss: 0.679568  [128064/150000]\n",
      "loss: 0.604731  [134464/150000]\n",
      "loss: 0.575098  [140864/150000]\n",
      "loss: 0.597137  [147264/150000]\n",
      "Epoch 5\n",
      "-------------------------------\n",
      "loss: 0.557888  [   64/150000]\n",
      "loss: 0.536265  [ 6464/150000]\n",
      "loss: 0.493845  [12864/150000]\n",
      "loss: 0.616729  [19264/150000]\n",
      "loss: 0.629660  [25664/150000]\n",
      "loss: 0.672249  [32064/150000]\n",
      "loss: 0.625117  [38464/150000]\n",
      "loss: 0.594650  [44864/150000]\n",
      "loss: 0.611802  [51264/150000]\n",
      "loss: 0.610690  [57664/150000]\n",
      "loss: 0.582970  [64064/150000]\n",
      "loss: 0.507220  [70464/150000]\n",
      "loss: 0.587091  [76864/150000]\n",
      "loss: 0.644539  [83264/150000]\n",
      "loss: 0.567560  [89664/150000]\n",
      "loss: 0.635086  [96064/150000]\n",
      "loss: 0.540519  [102464/150000]\n",
      "loss: 0.587662  [108864/150000]\n",
      "loss: 0.594138  [115264/150000]\n",
      "loss: 0.623967  [121664/150000]\n",
      "loss: 0.630961  [128064/150000]\n",
      "loss: 0.540283  [134464/150000]\n",
      "loss: 0.660469  [140864/150000]\n",
      "loss: 0.615367  [147264/150000]\n",
      "Epoch 6\n",
      "-------------------------------\n",
      "loss: 0.644627  [   64/150000]\n",
      "loss: 0.641388  [ 6464/150000]\n",
      "loss: 0.583667  [12864/150000]\n",
      "loss: 0.595985  [19264/150000]\n",
      "loss: 0.639247  [25664/150000]\n",
      "loss: 0.553457  [32064/150000]\n",
      "loss: 0.644644  [38464/150000]\n",
      "loss: 0.659022  [44864/150000]\n",
      "loss: 0.603649  [51264/150000]\n",
      "loss: 0.556295  [57664/150000]\n",
      "loss: 0.633961  [64064/150000]\n",
      "loss: 0.603780  [70464/150000]\n",
      "loss: 0.635701  [76864/150000]\n",
      "loss: 0.617778  [83264/150000]\n",
      "loss: 0.576959  [89664/150000]\n",
      "loss: 0.612733  [96064/150000]\n",
      "loss: 0.606709  [102464/150000]\n",
      "loss: 0.534224  [108864/150000]\n",
      "loss: 0.552378  [115264/150000]\n",
      "loss: 0.582934  [121664/150000]\n",
      "loss: 0.590858  [128064/150000]\n",
      "loss: 0.572298  [134464/150000]\n",
      "loss: 0.577786  [140864/150000]\n",
      "loss: 0.601727  [147264/150000]\n",
      "Epoch 7\n",
      "-------------------------------\n",
      "loss: 0.585471  [   64/150000]\n",
      "loss: 0.620201  [ 6464/150000]\n",
      "loss: 0.629633  [12864/150000]\n",
      "loss: 0.633278  [19264/150000]\n",
      "loss: 0.581919  [25664/150000]\n",
      "loss: 0.639833  [32064/150000]\n",
      "loss: 0.565880  [38464/150000]\n",
      "loss: 0.618099  [44864/150000]\n",
      "loss: 0.540124  [51264/150000]\n",
      "loss: 0.533662  [57664/150000]\n",
      "loss: 0.537237  [64064/150000]\n",
      "loss: 0.654931  [70464/150000]\n",
      "loss: 0.579782  [76864/150000]\n",
      "loss: 0.584689  [83264/150000]\n",
      "loss: 0.596409  [89664/150000]\n",
      "loss: 0.616381  [96064/150000]\n",
      "loss: 0.590769  [102464/150000]\n",
      "loss: 0.616326  [108864/150000]\n",
      "loss: 0.685181  [115264/150000]\n",
      "loss: 0.593606  [121664/150000]\n",
      "loss: 0.644492  [128064/150000]\n",
      "loss: 0.657713  [134464/150000]\n",
      "loss: 0.686037  [140864/150000]\n",
      "loss: 0.612704  [147264/150000]\n",
      "Epoch 8\n",
      "-------------------------------\n",
      "loss: 0.565326  [   64/150000]\n",
      "loss: 0.596956  [ 6464/150000]\n",
      "loss: 0.633713  [12864/150000]\n",
      "loss: 0.675944  [19264/150000]\n",
      "loss: 0.558952  [25664/150000]\n",
      "loss: 0.647076  [32064/150000]\n",
      "loss: 0.617525  [38464/150000]\n",
      "loss: 0.561403  [44864/150000]\n",
      "loss: 0.656842  [51264/150000]\n",
      "loss: 0.644154  [57664/150000]\n",
      "loss: 0.543379  [64064/150000]\n",
      "loss: 0.672034  [70464/150000]\n",
      "loss: 0.677683  [76864/150000]\n",
      "loss: 0.586226  [83264/150000]\n",
      "loss: 0.612088  [89664/150000]\n",
      "loss: 0.554074  [96064/150000]\n",
      "loss: 0.608314  [102464/150000]\n",
      "loss: 0.596135  [108864/150000]\n",
      "loss: 0.572143  [115264/150000]\n",
      "loss: 0.575213  [121664/150000]\n",
      "loss: 0.617696  [128064/150000]\n",
      "loss: 0.516614  [134464/150000]\n",
      "loss: 0.608312  [140864/150000]\n",
      "loss: 0.655292  [147264/150000]\n",
      "Epoch 9\n",
      "-------------------------------\n",
      "loss: 0.632591  [   64/150000]\n",
      "loss: 0.573968  [ 6464/150000]\n",
      "loss: 0.606144  [12864/150000]\n",
      "loss: 0.570658  [19264/150000]\n",
      "loss: 0.582340  [25664/150000]\n",
      "loss: 0.686753  [32064/150000]\n",
      "loss: 0.566058  [38464/150000]\n",
      "loss: 0.554912  [44864/150000]\n",
      "loss: 0.565513  [51264/150000]\n",
      "loss: 0.685594  [57664/150000]\n",
      "loss: 0.577988  [64064/150000]\n",
      "loss: 0.601425  [70464/150000]\n",
      "loss: 0.529391  [76864/150000]\n",
      "loss: 0.522878  [83264/150000]\n",
      "loss: 0.630615  [89664/150000]\n",
      "loss: 0.667440  [96064/150000]\n",
      "loss: 0.540676  [102464/150000]\n",
      "loss: 0.535263  [108864/150000]\n",
      "loss: 0.621468  [115264/150000]\n",
      "loss: 0.637567  [121664/150000]\n",
      "loss: 0.629170  [128064/150000]\n",
      "loss: 0.606112  [134464/150000]\n",
      "loss: 0.571968  [140864/150000]\n",
      "loss: 0.615397  [147264/150000]\n",
      "Epoch 10\n",
      "-------------------------------\n",
      "loss: 0.605752  [   64/150000]\n",
      "loss: 0.573386  [ 6464/150000]\n",
      "loss: 0.575619  [12864/150000]\n",
      "loss: 0.593930  [19264/150000]\n",
      "loss: 0.606027  [25664/150000]\n",
      "loss: 0.603035  [32064/150000]\n",
      "loss: 0.534000  [38464/150000]\n",
      "loss: 0.565585  [44864/150000]\n",
      "loss: 0.589906  [51264/150000]\n",
      "loss: 0.592201  [57664/150000]\n",
      "loss: 0.628924  [64064/150000]\n",
      "loss: 0.616412  [70464/150000]\n",
      "loss: 0.587669  [76864/150000]\n",
      "loss: 0.608327  [83264/150000]\n",
      "loss: 0.583130  [89664/150000]\n",
      "loss: 0.543986  [96064/150000]\n",
      "loss: 0.607370  [102464/150000]\n",
      "loss: 0.546562  [108864/150000]\n",
      "loss: 0.591624  [115264/150000]\n",
      "loss: 0.609809  [121664/150000]\n",
      "loss: 0.578402  [128064/150000]\n",
      "loss: 0.595384  [134464/150000]\n",
      "loss: 0.625442  [140864/150000]\n",
      "loss: 0.665480  [147264/150000]\n",
      "Epoch 11\n",
      "-------------------------------\n",
      "loss: 0.579572  [   64/150000]\n",
      "loss: 0.677842  [ 6464/150000]\n",
      "loss: 0.593931  [12864/150000]\n",
      "loss: 0.592321  [19264/150000]\n",
      "loss: 0.575612  [25664/150000]\n",
      "loss: 0.571065  [32064/150000]\n",
      "loss: 0.575749  [38464/150000]\n",
      "loss: 0.616480  [44864/150000]\n",
      "loss: 0.472566  [51264/150000]\n",
      "loss: 0.550193  [57664/150000]\n",
      "loss: 0.557135  [64064/150000]\n",
      "loss: 0.567849  [70464/150000]\n",
      "loss: 0.661146  [76864/150000]\n",
      "loss: 0.578843  [83264/150000]\n",
      "loss: 0.588202  [89664/150000]\n",
      "loss: 0.639270  [96064/150000]\n",
      "loss: 0.718008  [102464/150000]\n",
      "loss: 0.622295  [108864/150000]\n",
      "loss: 0.628525  [115264/150000]\n",
      "loss: 0.623000  [121664/150000]\n",
      "loss: 0.606138  [128064/150000]\n",
      "loss: 0.554370  [134464/150000]\n",
      "loss: 0.689069  [140864/150000]\n",
      "loss: 0.555399  [147264/150000]\n",
      "Epoch 12\n",
      "-------------------------------\n",
      "loss: 0.552356  [   64/150000]\n",
      "loss: 0.686734  [ 6464/150000]\n",
      "loss: 0.609447  [12864/150000]\n",
      "loss: 0.604392  [19264/150000]\n",
      "loss: 0.602954  [25664/150000]\n",
      "loss: 0.546178  [32064/150000]\n",
      "loss: 0.628506  [38464/150000]\n",
      "loss: 0.673439  [44864/150000]\n",
      "loss: 0.625517  [51264/150000]\n",
      "loss: 0.598829  [57664/150000]\n",
      "loss: 0.568111  [64064/150000]\n",
      "loss: 0.698848  [70464/150000]\n",
      "loss: 0.625230  [76864/150000]\n",
      "loss: 0.600533  [83264/150000]\n",
      "loss: 0.591708  [89664/150000]\n",
      "loss: 0.605737  [96064/150000]\n",
      "loss: 0.617584  [102464/150000]\n",
      "loss: 0.605771  [108864/150000]\n",
      "loss: 0.697467  [115264/150000]\n",
      "loss: 0.591232  [121664/150000]\n",
      "loss: 0.552443  [128064/150000]\n",
      "loss: 0.592739  [134464/150000]\n",
      "loss: 0.589756  [140864/150000]\n",
      "loss: 0.534506  [147264/150000]\n",
      "Epoch 13\n",
      "-------------------------------\n",
      "loss: 0.640633  [   64/150000]\n",
      "loss: 0.697667  [ 6464/150000]\n",
      "loss: 0.592239  [12864/150000]\n",
      "loss: 0.595909  [19264/150000]\n",
      "loss: 0.538048  [25664/150000]\n",
      "loss: 0.567052  [32064/150000]\n",
      "loss: 0.565347  [38464/150000]\n",
      "loss: 0.628676  [44864/150000]\n",
      "loss: 0.532067  [51264/150000]\n",
      "loss: 0.569317  [57664/150000]\n",
      "loss: 0.662629  [64064/150000]\n",
      "loss: 0.690312  [70464/150000]\n",
      "loss: 0.549885  [76864/150000]\n",
      "loss: 0.621373  [83264/150000]\n",
      "loss: 0.593378  [89664/150000]\n",
      "loss: 0.655877  [96064/150000]\n",
      "loss: 0.596402  [102464/150000]\n",
      "loss: 0.670918  [108864/150000]\n",
      "loss: 0.597230  [115264/150000]\n",
      "loss: 0.592003  [121664/150000]\n",
      "loss: 0.618691  [128064/150000]\n",
      "loss: 0.580073  [134464/150000]\n",
      "loss: 0.650928  [140864/150000]\n",
      "loss: 0.595747  [147264/150000]\n",
      "Epoch 14\n",
      "-------------------------------\n",
      "loss: 0.631570  [   64/150000]\n",
      "loss: 0.581386  [ 6464/150000]\n",
      "loss: 0.530600  [12864/150000]\n",
      "loss: 0.649409  [19264/150000]\n",
      "loss: 0.652399  [25664/150000]\n",
      "loss: 0.567224  [32064/150000]\n",
      "loss: 0.562777  [38464/150000]\n",
      "loss: 0.475368  [44864/150000]\n",
      "loss: 0.525190  [51264/150000]\n",
      "loss: 0.599928  [57664/150000]\n",
      "loss: 0.548746  [64064/150000]\n",
      "loss: 0.474745  [70464/150000]\n",
      "loss: 0.626452  [76864/150000]\n",
      "loss: 0.503386  [83264/150000]\n",
      "loss: 0.494949  [89664/150000]\n",
      "loss: 0.615882  [96064/150000]\n",
      "loss: 0.583681  [102464/150000]\n",
      "loss: 0.605108  [108864/150000]\n",
      "loss: 0.607096  [115264/150000]\n",
      "loss: 0.582837  [121664/150000]\n",
      "loss: 0.605536  [128064/150000]\n",
      "loss: 0.604692  [134464/150000]\n",
      "loss: 0.584882  [140864/150000]\n",
      "loss: 0.534502  [147264/150000]\n",
      "Epoch 15\n",
      "-------------------------------\n",
      "loss: 0.544695  [   64/150000]\n",
      "loss: 0.573055  [ 6464/150000]\n",
      "loss: 0.550669  [12864/150000]\n",
      "loss: 0.723938  [19264/150000]\n",
      "loss: 0.584465  [25664/150000]\n",
      "loss: 0.569426  [32064/150000]\n",
      "loss: 0.607056  [38464/150000]\n",
      "loss: 0.616925  [44864/150000]\n",
      "loss: 0.642344  [51264/150000]\n",
      "loss: 0.549334  [57664/150000]\n",
      "loss: 0.587071  [64064/150000]\n",
      "loss: 0.615041  [70464/150000]\n",
      "loss: 0.579657  [76864/150000]\n",
      "loss: 0.601171  [83264/150000]\n",
      "loss: 0.612851  [89664/150000]\n",
      "loss: 0.618960  [96064/150000]\n",
      "loss: 0.601881  [102464/150000]\n",
      "loss: 0.640874  [108864/150000]\n",
      "loss: 0.504944  [115264/150000]\n",
      "loss: 0.580753  [121664/150000]\n",
      "loss: 0.576069  [128064/150000]\n",
      "loss: 0.545511  [134464/150000]\n",
      "loss: 0.611074  [140864/150000]\n",
      "loss: 0.621706  [147264/150000]\n",
      "Epoch 16\n",
      "-------------------------------\n",
      "loss: 0.524734  [   64/150000]\n",
      "loss: 0.669807  [ 6464/150000]\n",
      "loss: 0.589392  [12864/150000]\n",
      "loss: 0.582379  [19264/150000]\n",
      "loss: 0.664578  [25664/150000]\n",
      "loss: 0.615774  [32064/150000]\n",
      "loss: 0.622845  [38464/150000]\n",
      "loss: 0.538043  [44864/150000]\n",
      "loss: 0.562914  [51264/150000]\n",
      "loss: 0.582615  [57664/150000]\n",
      "loss: 0.512658  [64064/150000]\n",
      "loss: 0.580139  [70464/150000]\n",
      "loss: 0.594151  [76864/150000]\n",
      "loss: 0.647114  [83264/150000]\n",
      "loss: 0.592874  [89664/150000]\n",
      "loss: 0.643142  [96064/150000]\n",
      "loss: 0.584972  [102464/150000]\n",
      "loss: 0.561617  [108864/150000]\n",
      "loss: 0.597275  [115264/150000]\n",
      "loss: 0.599875  [121664/150000]\n",
      "loss: 0.532628  [128064/150000]\n",
      "loss: 0.521613  [134464/150000]\n",
      "loss: 0.664630  [140864/150000]\n",
      "loss: 0.608385  [147264/150000]\n",
      "Epoch 17\n",
      "-------------------------------\n",
      "loss: 0.621746  [   64/150000]\n",
      "loss: 0.511989  [ 6464/150000]\n",
      "loss: 0.563653  [12864/150000]\n",
      "loss: 0.562508  [19264/150000]\n",
      "loss: 0.498100  [25664/150000]\n",
      "loss: 0.594418  [32064/150000]\n",
      "loss: 0.583726  [38464/150000]\n",
      "loss: 0.588750  [44864/150000]\n",
      "loss: 0.521480  [51264/150000]\n",
      "loss: 0.579815  [57664/150000]\n",
      "loss: 0.542970  [64064/150000]\n",
      "loss: 0.544266  [70464/150000]\n",
      "loss: 0.571421  [76864/150000]\n",
      "loss: 0.526584  [83264/150000]\n",
      "loss: 0.591572  [89664/150000]\n",
      "loss: 0.611933  [96064/150000]\n",
      "loss: 0.562910  [102464/150000]\n",
      "loss: 0.613617  [108864/150000]\n",
      "loss: 0.639856  [115264/150000]\n",
      "loss: 0.555695  [121664/150000]\n",
      "loss: 0.595588  [128064/150000]\n",
      "loss: 0.634104  [134464/150000]\n",
      "loss: 0.585836  [140864/150000]\n",
      "loss: 0.635098  [147264/150000]\n",
      "Epoch 18\n",
      "-------------------------------\n",
      "loss: 0.599146  [   64/150000]\n",
      "loss: 0.618983  [ 6464/150000]\n",
      "loss: 0.562647  [12864/150000]\n",
      "loss: 0.629981  [19264/150000]\n",
      "loss: 0.557569  [25664/150000]\n",
      "loss: 0.644682  [32064/150000]\n",
      "loss: 0.552329  [38464/150000]\n",
      "loss: 0.632133  [44864/150000]\n",
      "loss: 0.667953  [51264/150000]\n",
      "loss: 0.579287  [57664/150000]\n",
      "loss: 0.551793  [64064/150000]\n",
      "loss: 0.516235  [70464/150000]\n",
      "loss: 0.623689  [76864/150000]\n",
      "loss: 0.583543  [83264/150000]\n",
      "loss: 0.602581  [89664/150000]\n",
      "loss: 0.617562  [96064/150000]\n",
      "loss: 0.589883  [102464/150000]\n",
      "loss: 0.594558  [108864/150000]\n",
      "loss: 0.591930  [115264/150000]\n",
      "loss: 0.598964  [121664/150000]\n",
      "loss: 0.631221  [128064/150000]\n",
      "loss: 0.569307  [134464/150000]\n",
      "loss: 0.626202  [140864/150000]\n",
      "loss: 0.579201  [147264/150000]\n",
      "Epoch 19\n",
      "-------------------------------\n",
      "loss: 0.588934  [   64/150000]\n",
      "loss: 0.588312  [ 6464/150000]\n",
      "loss: 0.513917  [12864/150000]\n",
      "loss: 0.606465  [19264/150000]\n",
      "loss: 0.592342  [25664/150000]\n",
      "loss: 0.615711  [32064/150000]\n",
      "loss: 0.557372  [38464/150000]\n",
      "loss: 0.559006  [44864/150000]\n",
      "loss: 0.585443  [51264/150000]\n",
      "loss: 0.485954  [57664/150000]\n",
      "loss: 0.589985  [64064/150000]\n",
      "loss: 0.587740  [70464/150000]\n",
      "loss: 0.629844  [76864/150000]\n",
      "loss: 0.521275  [83264/150000]\n",
      "loss: 0.603965  [89664/150000]\n",
      "loss: 0.644880  [96064/150000]\n",
      "loss: 0.630848  [102464/150000]\n",
      "loss: 0.571996  [108864/150000]\n",
      "loss: 0.580071  [115264/150000]\n",
      "loss: 0.593456  [121664/150000]\n",
      "loss: 0.551542  [128064/150000]\n",
      "loss: 0.611395  [134464/150000]\n",
      "loss: 0.577660  [140864/150000]\n",
      "loss: 0.612326  [147264/150000]\n",
      "Epoch 20\n",
      "-------------------------------\n",
      "loss: 0.627417  [   64/150000]\n",
      "loss: 0.637460  [ 6464/150000]\n",
      "loss: 0.666766  [12864/150000]\n",
      "loss: 0.531427  [19264/150000]\n",
      "loss: 0.562119  [25664/150000]\n",
      "loss: 0.587002  [32064/150000]\n",
      "loss: 0.652636  [38464/150000]\n",
      "loss: 0.559747  [44864/150000]\n",
      "loss: 0.587982  [51264/150000]\n",
      "loss: 0.601106  [57664/150000]\n",
      "loss: 0.565837  [64064/150000]\n",
      "loss: 0.607227  [70464/150000]\n",
      "loss: 0.626141  [76864/150000]\n",
      "loss: 0.640508  [83264/150000]\n",
      "loss: 0.605786  [89664/150000]\n",
      "loss: 0.608159  [96064/150000]\n",
      "loss: 0.530527  [102464/150000]\n",
      "loss: 0.587791  [108864/150000]\n",
      "loss: 0.593820  [115264/150000]\n",
      "loss: 0.615074  [121664/150000]\n",
      "loss: 0.616388  [128064/150000]\n",
      "loss: 0.569421  [134464/150000]\n",
      "loss: 0.607489  [140864/150000]\n",
      "loss: 0.645023  [147264/150000]\n",
      "Epoch 21\n",
      "-------------------------------\n",
      "loss: 0.603664  [   64/150000]\n",
      "loss: 0.614986  [ 6464/150000]\n",
      "loss: 0.521039  [12864/150000]\n",
      "loss: 0.547322  [19264/150000]\n",
      "loss: 0.577473  [25664/150000]\n",
      "loss: 0.597063  [32064/150000]\n",
      "loss: 0.585668  [38464/150000]\n",
      "loss: 0.541477  [44864/150000]\n",
      "loss: 0.588172  [51264/150000]\n",
      "loss: 0.645711  [57664/150000]\n",
      "loss: 0.617174  [64064/150000]\n",
      "loss: 0.659786  [70464/150000]\n",
      "loss: 0.518750  [76864/150000]\n",
      "loss: 0.564853  [83264/150000]\n",
      "loss: 0.540514  [89664/150000]\n",
      "loss: 0.677545  [96064/150000]\n",
      "loss: 0.583586  [102464/150000]\n",
      "loss: 0.587650  [108864/150000]\n",
      "loss: 0.618852  [115264/150000]\n",
      "loss: 0.546123  [121664/150000]\n",
      "loss: 0.611922  [128064/150000]\n",
      "loss: 0.769938  [134464/150000]\n",
      "loss: 0.654696  [140864/150000]\n",
      "loss: 0.555877  [147264/150000]\n",
      "Epoch 22\n",
      "-------------------------------\n",
      "loss: 0.546781  [   64/150000]\n",
      "loss: 0.663820  [ 6464/150000]\n",
      "loss: 0.586681  [12864/150000]\n",
      "loss: 0.545602  [19264/150000]\n",
      "loss: 0.622281  [25664/150000]\n",
      "loss: 0.613386  [32064/150000]\n",
      "loss: 0.679810  [38464/150000]\n",
      "loss: 0.561913  [44864/150000]\n",
      "loss: 0.588024  [51264/150000]\n",
      "loss: 0.646534  [57664/150000]\n",
      "loss: 0.567236  [64064/150000]\n",
      "loss: 0.582543  [70464/150000]\n",
      "loss: 0.581364  [76864/150000]\n",
      "loss: 0.589139  [83264/150000]\n",
      "loss: 0.651509  [89664/150000]\n",
      "loss: 0.562445  [96064/150000]\n",
      "loss: 0.679964  [102464/150000]\n",
      "loss: 0.560593  [108864/150000]\n",
      "loss: 0.535673  [115264/150000]\n",
      "loss: 0.605118  [121664/150000]\n",
      "loss: 0.591122  [128064/150000]\n",
      "loss: 0.576950  [134464/150000]\n",
      "loss: 0.554719  [140864/150000]\n",
      "loss: 0.568256  [147264/150000]\n",
      "Epoch 23\n",
      "-------------------------------\n",
      "loss: 0.515077  [   64/150000]\n",
      "loss: 0.553921  [ 6464/150000]\n",
      "loss: 0.577074  [12864/150000]\n",
      "loss: 0.585402  [19264/150000]\n",
      "loss: 0.611172  [25664/150000]\n",
      "loss: 0.587801  [32064/150000]\n",
      "loss: 0.588383  [38464/150000]\n",
      "loss: 0.711319  [44864/150000]\n",
      "loss: 0.527017  [51264/150000]\n",
      "loss: 0.678208  [57664/150000]\n",
      "loss: 0.589850  [64064/150000]\n",
      "loss: 0.584371  [70464/150000]\n",
      "loss: 0.581527  [76864/150000]\n",
      "loss: 0.653242  [83264/150000]\n",
      "loss: 0.613740  [89664/150000]\n",
      "loss: 0.525126  [96064/150000]\n",
      "loss: 0.609433  [102464/150000]\n",
      "loss: 0.608985  [108864/150000]\n",
      "loss: 0.682752  [115264/150000]\n",
      "loss: 0.592517  [121664/150000]\n",
      "loss: 0.597739  [128064/150000]\n",
      "loss: 0.542855  [134464/150000]\n",
      "loss: 0.600933  [140864/150000]\n",
      "loss: 0.548048  [147264/150000]\n",
      "Epoch 24\n",
      "-------------------------------\n",
      "loss: 0.538409  [   64/150000]\n",
      "loss: 0.587732  [ 6464/150000]\n",
      "loss: 0.553931  [12864/150000]\n",
      "loss: 0.615992  [19264/150000]\n",
      "loss: 0.546581  [25664/150000]\n",
      "loss: 0.550231  [32064/150000]\n",
      "loss: 0.648659  [38464/150000]\n",
      "loss: 0.633638  [44864/150000]\n",
      "loss: 0.550732  [51264/150000]\n",
      "loss: 0.543928  [57664/150000]\n",
      "loss: 0.617104  [64064/150000]\n",
      "loss: 0.560582  [70464/150000]\n",
      "loss: 0.669584  [76864/150000]\n",
      "loss: 0.601878  [83264/150000]\n",
      "loss: 0.527612  [89664/150000]\n",
      "loss: 0.572111  [96064/150000]\n",
      "loss: 0.598589  [102464/150000]\n",
      "loss: 0.603640  [108864/150000]\n",
      "loss: 0.608930  [115264/150000]\n",
      "loss: 0.534105  [121664/150000]\n",
      "loss: 0.629878  [128064/150000]\n",
      "loss: 0.611613  [134464/150000]\n",
      "loss: 0.513288  [140864/150000]\n",
      "loss: 0.635841  [147264/150000]\n",
      "Epoch 25\n",
      "-------------------------------\n",
      "loss: 0.557434  [   64/150000]\n",
      "loss: 0.615803  [ 6464/150000]\n",
      "loss: 0.579832  [12864/150000]\n",
      "loss: 0.575765  [19264/150000]\n",
      "loss: 0.606995  [25664/150000]\n",
      "loss: 0.632700  [32064/150000]\n",
      "loss: 0.632381  [38464/150000]\n",
      "loss: 0.615837  [44864/150000]\n",
      "loss: 0.587369  [51264/150000]\n",
      "loss: 0.600212  [57664/150000]\n",
      "loss: 0.616872  [64064/150000]\n",
      "loss: 0.609934  [70464/150000]\n",
      "loss: 0.662792  [76864/150000]\n",
      "loss: 0.589709  [83264/150000]\n",
      "loss: 0.618774  [89664/150000]\n",
      "loss: 0.645855  [96064/150000]\n",
      "loss: 0.551524  [102464/150000]\n",
      "loss: 0.533778  [108864/150000]\n",
      "loss: 0.577648  [115264/150000]\n",
      "loss: 0.544056  [121664/150000]\n",
      "loss: 0.614962  [128064/150000]\n",
      "loss: 0.539947  [134464/150000]\n",
      "loss: 0.612202  [140864/150000]\n",
      "loss: 0.560787  [147264/150000]\n",
      "Epoch 26\n",
      "-------------------------------\n",
      "loss: 0.562039  [   64/150000]\n",
      "loss: 0.557390  [ 6464/150000]\n",
      "loss: 0.611007  [12864/150000]\n",
      "loss: 0.615194  [19264/150000]\n",
      "loss: 0.574516  [25664/150000]\n",
      "loss: 0.613461  [32064/150000]\n",
      "loss: 0.606872  [38464/150000]\n",
      "loss: 0.565459  [44864/150000]\n",
      "loss: 0.585175  [51264/150000]\n",
      "loss: 0.625837  [57664/150000]\n",
      "loss: 0.561817  [64064/150000]\n",
      "loss: 0.596336  [70464/150000]\n",
      "loss: 0.600057  [76864/150000]\n",
      "loss: 0.573806  [83264/150000]\n",
      "loss: 0.641340  [89664/150000]\n",
      "loss: 0.608286  [96064/150000]\n",
      "loss: 0.649721  [102464/150000]\n",
      "loss: 0.671843  [108864/150000]\n",
      "loss: 0.564814  [115264/150000]\n",
      "loss: 0.632006  [121664/150000]\n",
      "loss: 0.537901  [128064/150000]\n",
      "loss: 0.519129  [134464/150000]\n",
      "loss: 0.604893  [140864/150000]\n",
      "loss: 0.565878  [147264/150000]\n",
      "Epoch 27\n",
      "-------------------------------\n",
      "loss: 0.637899  [   64/150000]\n",
      "loss: 0.619308  [ 6464/150000]\n",
      "loss: 0.565980  [12864/150000]\n",
      "loss: 0.580520  [19264/150000]\n",
      "loss: 0.517601  [25664/150000]\n",
      "loss: 0.600046  [32064/150000]\n",
      "loss: 0.522602  [38464/150000]\n",
      "loss: 0.585224  [44864/150000]\n",
      "loss: 0.616364  [51264/150000]\n",
      "loss: 0.607755  [57664/150000]\n",
      "loss: 0.672700  [64064/150000]\n",
      "loss: 0.615942  [70464/150000]\n",
      "loss: 0.563604  [76864/150000]\n",
      "loss: 0.516980  [83264/150000]\n",
      "loss: 0.568126  [89664/150000]\n",
      "loss: 0.643335  [96064/150000]\n",
      "loss: 0.598452  [102464/150000]\n",
      "loss: 0.645684  [108864/150000]\n",
      "loss: 0.615591  [115264/150000]\n",
      "loss: 0.621618  [121664/150000]\n",
      "loss: 0.534854  [128064/150000]\n",
      "loss: 0.589854  [134464/150000]\n",
      "loss: 0.635436  [140864/150000]\n",
      "loss: 0.554766  [147264/150000]\n",
      "Epoch 28\n",
      "-------------------------------\n",
      "loss: 0.521061  [   64/150000]\n",
      "loss: 0.636044  [ 6464/150000]\n",
      "loss: 0.637459  [12864/150000]\n",
      "loss: 0.643848  [19264/150000]\n",
      "loss: 0.644321  [25664/150000]\n",
      "loss: 0.495741  [32064/150000]\n",
      "loss: 0.607640  [38464/150000]\n",
      "loss: 0.588970  [44864/150000]\n",
      "loss: 0.559616  [51264/150000]\n",
      "loss: 0.594282  [57664/150000]\n",
      "loss: 0.576745  [64064/150000]\n",
      "loss: 0.550133  [70464/150000]\n",
      "loss: 0.598407  [76864/150000]\n",
      "loss: 0.547898  [83264/150000]\n",
      "loss: 0.620289  [89664/150000]\n",
      "loss: 0.625945  [96064/150000]\n",
      "loss: 0.588795  [102464/150000]\n",
      "loss: 0.564310  [108864/150000]\n",
      "loss: 0.471800  [115264/150000]\n",
      "loss: 0.661256  [121664/150000]\n",
      "loss: 0.512393  [128064/150000]\n",
      "loss: 0.518628  [134464/150000]\n",
      "loss: 0.637960  [140864/150000]\n",
      "loss: 0.634269  [147264/150000]\n",
      "Epoch 29\n",
      "-------------------------------\n",
      "loss: 0.532436  [   64/150000]\n",
      "loss: 0.582553  [ 6464/150000]\n",
      "loss: 0.599198  [12864/150000]\n",
      "loss: 0.599311  [19264/150000]\n",
      "loss: 0.537017  [25664/150000]\n",
      "loss: 0.545210  [32064/150000]\n",
      "loss: 0.594809  [38464/150000]\n",
      "loss: 0.560428  [44864/150000]\n",
      "loss: 0.585562  [51264/150000]\n",
      "loss: 0.615488  [57664/150000]\n",
      "loss: 0.601441  [64064/150000]\n",
      "loss: 0.586801  [70464/150000]\n",
      "loss: 0.612262  [76864/150000]\n",
      "loss: 0.569715  [83264/150000]\n",
      "loss: 0.617154  [89664/150000]\n",
      "loss: 0.615478  [96064/150000]\n",
      "loss: 0.627287  [102464/150000]\n",
      "loss: 0.594675  [108864/150000]\n",
      "loss: 0.527844  [115264/150000]\n",
      "loss: 0.601432  [121664/150000]\n",
      "loss: 0.560899  [128064/150000]\n",
      "loss: 0.590129  [134464/150000]\n",
      "loss: 0.634971  [140864/150000]\n",
      "loss: 0.612034  [147264/150000]\n",
      "Epoch 30\n",
      "-------------------------------\n",
      "loss: 0.663320  [   64/150000]\n",
      "loss: 0.590303  [ 6464/150000]\n",
      "loss: 0.548620  [12864/150000]\n",
      "loss: 0.606458  [19264/150000]\n",
      "loss: 0.551339  [25664/150000]\n",
      "loss: 0.597070  [32064/150000]\n",
      "loss: 0.568118  [38464/150000]\n",
      "loss: 0.656885  [44864/150000]\n",
      "loss: 0.517651  [51264/150000]\n",
      "loss: 0.619143  [57664/150000]\n",
      "loss: 0.576512  [64064/150000]\n",
      "loss: 0.551789  [70464/150000]\n",
      "loss: 0.639050  [76864/150000]\n",
      "loss: 0.568361  [83264/150000]\n",
      "loss: 0.549884  [89664/150000]\n",
      "loss: 0.634776  [96064/150000]\n",
      "loss: 0.555386  [102464/150000]\n",
      "loss: 0.525088  [108864/150000]\n",
      "loss: 0.613388  [115264/150000]\n",
      "loss: 0.529327  [121664/150000]\n",
      "loss: 0.554036  [128064/150000]\n",
      "loss: 0.570808  [134464/150000]\n",
      "loss: 0.573866  [140864/150000]\n",
      "loss: 0.593912  [147264/150000]\n",
      "Done!\n",
      "Train data:\n",
      "AUC value is: 0.6999572362931573\n",
      "Accuracy is: 0.6615666666666666\n",
      "Test data:\n",
      "AUC value is: 0.7051648361054951\n",
      "Accuracy is: 0.66606\n"
     ]
    }
   ],
   "source": [
    "attack_model = shadow_attack(sha_models=sha_models, tar_model=tar_model, model_num=num_shadowsets, weight_dir=weight_dir, data_name=DATA_NAME, model=MODEL, model_transform=model_transform, \n",
    "                  model_epochs=EPOCHS, batch_size=BATCH_SIZE, learning_rate=attack_lr, attack_epochs=30, attack_transform=attack_transform, \n",
    "                  device=device, prop_keep=0.5, top_k=None, attack_class=attack_class)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "ab8c2490-c230-4516-a19a-df84a3779011",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Attack_NN(\n",
       "  (linear_relu_stack): Sequential(\n",
       "    (0): Linear(in_features=11, out_features=128, bias=True)\n",
       "    (1): ReLU()\n",
       "    (2): Linear(in_features=128, out_features=64, bias=True)\n",
       "    (3): ReLU()\n",
       "    (4): Linear(in_features=64, out_features=1, bias=True)\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "attack_model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "d1f87436-bae2-410f-a025-e9757ecd17d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "targetX = conf_data_all[tar_model].astype(np.float32)\n",
    "targetY = train_keep[tar_model]\n",
    "targetX = np.concatenate((targetX, Y_data.reshape(Y_data.shape[0],1)), 1)\n",
    "targetX = targetX.astype(np.float32)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "ebd65e38-9469-4c5f-a5a3-041b675a9d3c",
   "metadata": {},
   "outputs": [],
   "source": [
    "top_k = None\n",
    "if top_k:\n",
    "    # 仅使用概率向量的前3个值\n",
    "    targetX, _ = get_top_k_conf(top_k, targetX, targetX)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "8ba8d2b7-7d6c-4e17-95bd-f854e8af5af9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AUC value is: 0.7051648425054993\n",
      "Accuracy is: 0.66606\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.66606"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "shadow_attack_data = CustomDataset(targetX, targetY, attack_transform)\n",
    "shadow_attack_dataloader = DataLoader(shadow_attack_data, batch_size=batch_size, shuffle=True)\n",
    "attack_test_scores, attack_test_mem = get_attack_pred(shadow_attack_dataloader, attack_model, device)\n",
    "attack_test_scores, attack_test_mem = attack_test_scores.detach().cpu().numpy(), attack_test_mem.detach().cpu().numpy()\n",
    "evaluate_ROC(attack_test_scores, attack_test_mem)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "c8cb250e-ad72-40b3-8967-46b8538be791",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AUC value is: 0.6892114804089503\n",
      "Accuracy is: 0.6596\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.6596"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "evaluate_ROC(attack_test_scores[risk_rank[:2500]], attack_test_mem[risk_rank[:2500]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eebaa471-2271-4310-b936-1030edb6f096",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4bbfa8f-bd1a-46f6-9b79-a7c758d30f27",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b077751a-c0ee-4e39-9f70-41b791d348e6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f06a3e24-5a57-472a-b6f0-78961403f471",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40ceb18e-621c-4c72-8ef7-94498c7b65c5",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "30abf80e-2b00-4b70-ac0c-a7099f987cc4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f0ae045-14bd-4159-948c-8881f74cd181",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d64311d6-c09d-47b3-8076-f11eb10134aa",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "87d308e9-be9d-40fb-be9e-e84efc339052",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0308f234-469f-4670-b4e4-51973cb27ce4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "a9b3ad57-7f95-4bc7-8057-05aa0ca4e10a",
   "metadata": {},
   "source": [
    "### 绘制攻击成功率随风险变化曲线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "03e43bb9-0680-487b-8433-805cb202031f",
   "metadata": {},
   "outputs": [],
   "source": [
    "pred_all = conf_data_all.argmax(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "b7dda5b4-e79d-40b7-beb8-86d21143ac11",
   "metadata": {},
   "outputs": [],
   "source": [
    "base_att = (pred_all == Y_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "a79890e7-c8ea-4ddd-9e0a-c51831260ad9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(100, 50000)"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "base_att.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "18020329-0447-496c-bffa-a59f865df12c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(100, 50000)"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_keep.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "67ad94bc-8667-4f2b-ab7b-3d32a98e97d8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(50000,)"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pri_risk_all.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "973858e9-c4fd-47cd-9941-c5730dfff80a",
   "metadata": {},
   "outputs": [],
   "source": [
    "X_axi = []\n",
    "Y_axi = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "4d44c0fa-c7b9-4f39-a245-0f8e3671141c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(50000,)"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pri_risk_rank.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "030de03c-e397-4141-8f84-6cd9910e91a7",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# 输入loss_data_all，pri_risk_rank，train_keep，conf_data_all，pri_risk_all\n",
    "\n",
    "for i in range(100): # 对数据下标进行计数\n",
    "    start = i * 500\n",
    "    end = (i+1) * 500\n",
    "    risk_t = pri_risk_all[pri_risk_rank[start:end]]\n",
    "    for j in range(100): # 对目标模型进行计数\n",
    "        pred_temp = base_att[j][pri_risk_rank[start:end]]\n",
    "        mem_temp = train_keep[j][pri_risk_rank[start:end]]\n",
    "        if j==0:\n",
    "            pred_t = pred_temp\n",
    "            mem_t = mem_temp\n",
    "        else:\n",
    "            pred_t = np.concatenate((pred_t, pred_temp), 0)\n",
    "            mem_t = np.concatenate((mem_t, mem_temp), 0)\n",
    "    acc = metrics.accuracy_score(mem_t, pred_t)\n",
    "    risk = np.mean(risk_t)\n",
    "    X_axi.append(risk)\n",
    "    Y_axi.append(acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a4df62ec-4eb6-4c8f-a522-737a9e0d0e06",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "238bf52f-5f07-4176-9642-bd34be61a5a6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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B1cHAMBFhB9ctf2nsjX5651KOpguSYoJC9RLd3TUda3CHFwZAABlEX5wxXILi/XW8v1675eDKjIb8vXy0OP9W2psvxj5ejF/DwDAORF+cEV+2XdaE7/cruMZeZKkm9o21Au3d1BUPQY1AwCcG+EHNks+fFYPz9+oQrNFkaH+euH2Drq5fbijywIAoEocPhJ15syZatasmfz8/BQXF6f169dX2n7GjBlq06aN/P39FRUVpSeffFL5+fk1VC2OZ+TpTx+WBJ/4dg21LKEfwQcA4FJsDj+jRo3SypUr7fLhCxYsUEJCgqZOnapNmzapS5cuGjhwoE6dOlVu+08++UQTJ07U1KlTtXv3bs2ZM0cLFizQ3/72N7vUg8rlFhZr7PsblXauUG0jgvTGvd0U4EPnIQDAtdgcfjIzMxUfH69WrVrp5Zdf1vHjx6/4w6dPn66xY8dq9OjRat++vWbPnq2AgADNnTu33PZr1qxRnz59dN9996lZs2YaMGCAhg8fftneIlw9i8XQU59v1a6TWaof6KP3RnVXoC/BBwDgemwOP19//bWOHz+uRx99VAsWLFCzZs00aNAgffHFFyoqKqrydgoLC5WcnKz4+PiLxXh4KD4+XklJSeWu07t3byUnJ1vDzsGDB/X999/r1ltvrfBzCgoKlJWVVeoF272RuE//tyNF3p4mzX4gVk3qMrAZAOCarmjMT4MGDZSQkKCtW7dq3bp1atmypR544AE1btxYTz75pPbt23fZbaSlpclsNis8vPR4kfDwcKWkpJS7zn333aeXXnpJ1113nby9vdWiRQvdcMMNlV72mjZtmkJCQqyvqKgo23YW+t+2E3ojseSY/r8hnXQtz+cCALiwqxrwfPLkSS1btkzLli2Tp6enbr31Vm3fvl3t27fX66+/bq8arVasWKGXX35Z//3vf7Vp0yYtWrRIixcv1t///vcK15k0aZIyMzOtr6NHj9q9rtpsx/FM/XXhVknSmOua655rCY8AANdm86CNoqIiffvtt5o3b56WLl2qzp0764knntB9992n4OBgSdJXX32lhx56SE8++WSF2wkLC5Onp6dSU1NLLU9NTVVERES560yePFkPPPCAxowZI0nq1KmTcnJy9Mgjj+i5556Th0fZLOfr6ytfX19bdxOSTmXla+wHG5VfZNH1rRto0q3tHF0SAABXzebw06hR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8wPAZjfccIPGjx+v8ePHKyQkRGFhYZo8ebIufVRgs2bN9Pe//10jR45UcHCwHnnkkVKXvSwWi5o0aaJZs2aV2vbmzZvl4eGhw4cPS5KmT5+uTp06KTAwUFFRUXrsscd07ty5UuusXr1aN9xwgwICAlS3bl0NHDhQZ8+e1QcffKD69euroKCgVPshQ4bogQceKHffLtS4YMECXX/99fLz89PHH39c5lLW1q1bdeONNyooKEjBwcGKjY3Vxo0by93m6dOn1b17d915551lagFQ8wg/AK7I+++/Ly8vL61fv15vvPGGpk+frvfee69Um3//+9/q0qWLNm/erMmTJ5d6z8PDQ8OHD9cnn3xSavnHH3+sPn36KDo62truzTff1M6dO/X+++9r+fLleuaZZ6ztt2zZoptuuknt27dXUlKSVq1apcGDB8tsNuvuu++W2WzWt99+a21/6tQpLV68WA899FCl+zdx4kRNmDBBu3fv1sCBA8u8P2LECDVp0kQbNmxQcnKyJk6cKG9v7zLtjh49qr59+6pjx4764osv5OvrW+nnAqgBV/ysegBu6/rrrzfatWtnWCwW67Jnn33WaNeunfXn6OhoY8iQIaXWO3TokCHJ2Lx5s2EYhrF582bDZDIZhw8fNgzDMMxmsxEZGWnMmjWrws9euHChUb9+fevPw4cPN/r06VNh+0cffdQYNGiQ9efXXnvNiImJKVV7eTXOmDGj1PJ58+YZISEh1p+DgoKM+fPnl7uNC2337NljREVFGX/5y18q/DwANY+eHwBXpGfPnjKZTNafe/XqpX379slsNluXde/evdJtdO3aVe3atbP2/vz88886deqU7r77bmubH3/8UTfddJMiIyMVFBSkBx54QOnp6crNzZV0seenImPHjtXSpUt1/PhxSSV3Yj344IOlai/P5WpPSEjQmDFjFB8fr3/+8586cOBAqffz8vLUt29fDR06VG+88cZlPw9AzSH8AKg2gYGBl20zYsQIa/j55JNPdMstt6h+/fqSSsbf/OEPf1Dnzp315ZdfKjk5WTNnzpRUMoBa0mUHIXfr1k1dunTRBx98oOTkZO3cuVMPPvjgVdf+wgsvaOfOnbrtttu0fPlytW/fXl999ZX1fV9fX8XHx+t///ufNXgBcA6EHwBXZN26daV+Xrt2rVq1aiVPT0+btnPfffdpx44dSk5O1hdffKERI0ZY30tOTpbFYtFrr72mnj17qnXr1jpx4kSp9Tt37qzExMRKP2PMmDGaP3++5s2bp/j4eEVFRdlUY0Vat26tJ598UkuXLtXQoUM1b94863seHh768MMPFRsbqxtvvLFM3QAch/AD4IocOXJECQkJ2rt3rz799FO99dZbmjBhgs3badasmXr37q2HH35YZrNZt99+u/W9li1bqqioSG+99ZYOHjyoDz/8ULNnzy61/qRJk7RhwwY99thj2rZtm/bs2aNZs2YpLS3N2ua+++7TsWPH9O677152oHNV5OXlafz48VqxYoUOHz6s1atXa8OGDWrXrl2pdp6envr444/VpUsX9e/fXykpKVf92QCuHuEHwBUZOXKk8vLy1KNHD40bN04TJkzQI488ckXbGjFihLZu3ao777yz1GWsLl26aPr06XrllVfUsWNHffzxx5o2bVqpdVu3bq2lS5dq69at6tGjh3r16qVvvvlGXl4XpzELCQnRXXfdpTp16mjIkCFXVOOlPD09lZ6erpEjR6p169a65557NGjQIL344otl2np5eenTTz9Vhw4d1L9/f506deqqPx/A1TEZxiUTcwBAFdxwww3q2rWrZsyY4ehSquymm25Shw4d9Oabbzq6FAAOxgzPAGq1s2fPasWKFVqxYoX++9//OrocAE6A8AOgVuvWrZvOnj2rV155RW3atHF0OQCcAJe9AACAW2HAMwAAcCuEHwAA4FYIPwAAwK0QfgAAgFsh/AAAALdC+AEAAG6F8AMAANwK4QcAALiV/w+aIdaL3oII1AAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "df=pd.DataFrame({'xvalues': X_axi, 'yvalues': Y_axi })\n",
    " \n",
    "# plot\n",
    "plt.plot( 'xvalues', 'yvalues', data=df)\n",
    "plt.xlabel(\"privacy risk\")\n",
    "plt.ylabel(\"attack accuracy\")\n",
    "# show the graph\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2ee4f5ad-e959-4f63-bde3-78c7e25fc0e4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "48d74a89-2c75-453a-a3b2-3fd906337030",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "025ed341-77fd-4f0e-b2cf-1ac59f0e74af",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "8e1a4ee1-0c47-411a-b98b-d7713d949e09",
   "metadata": {},
   "source": [
    "### 绘制损失分布差异"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "ecd477a2-9df6-4a4a-ba78-716c2d669d45",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "id": "2abddba4-ae48-405a-beb5-c45daf231d6d",
   "metadata": {},
   "outputs": [],
   "source": [
    "idx = 31000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "id": "0421a068-0678-435b-86b7-9f37862cc816",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 需要使用loss_data_all，pri_risk_rank，train_keep\n",
    "dat_in = []\n",
    "dat_out = []\n",
    "for i in range(loss_data_all.shape[1]):\n",
    "    dat_in.append((loss_data_all[train_keep[:,i],i]))\n",
    "    dat_out.append((loss_data_all[~train_keep[:,i],i]))\n",
    "dat_in = np.array(dat_in)\n",
    "dat_out = np.array(dat_out)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "37c2030e-d91f-4fdf-9a5a-e246ca594916",
   "metadata": {},
   "outputs": [],
   "source": [
    "mem1 = dat_in[pri_risk_rank[idx]]\n",
    "non_mem1 = dat_out[pri_risk_rank[idx]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "5612c786-26df-4ff0-9c42-2af62fa46b0f",
   "metadata": {},
   "outputs": [],
   "source": [
    "mem1 = mem1.reshape(mem1.shape[0], 1)\n",
    "non_mem1 = non_mem1.reshape(non_mem1.shape[0], 1)\n",
    "\n",
    "arr = np.concatenate((mem1, non_mem1), 1)\n",
    "\n",
    "df = pd.DataFrame(arr, columns=['loss','out'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "5a3fd823-c33a-4c78-8829-e7bb6410bc02",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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J07Uzp07lZOTY/dojsI7Moja+++/r9TUVF133XWSpEGDBhExhjt06JA++OADzZ492+5REAPDhw9XSUmJJGnYsGHKzc3V6dOn7R0K3bZ7926NGzdOI0eOVP/+/TV79mz913/9l91jOQ4h04dt375dN910k0aMGCGXy6VNmzZdcJ81a9aooKBAbrdbU6ZM0e7du7v9/IcOHVL//v110003acKECXr00UdjOD0+L977U5LuueceVVZWxmhiXEwi9mmbvXv3KhQKKS8vr5dTo7t6u3+PHz+ukSNHRq6PHDlSx44dS8ToRiFk+rDGxkZdddVVWrNmTYe3v/jiiyorK9Py5cv1zjvv6KqrrtKsWbNUV1cXuU9JSYmuuOKKCy7Hjx9Xa2ur/vSnP+mpp57Srl27tHXrVm3dujVRm3fJiff+/P3vf6+xY8dq7NixidqkS16892mb06dP69vf/rbWrVsX923C/4vF/kU3WLgkSLJefvnldstKS0utxYsXR66HQiFrxIgRVmVlZbeec+fOndbMmTMj11etWmWtWrUqJvOia/HYn/fff7912WWXWaNGjbJycnKsrKwsa8WKFbEcG12Ixz61LMtqamqyrrvuOuvXv/51rEZFFKLZvzt27LDmzp0buf2uu+6ynn/++YTMaxLekblEnT9/Xnv37tWMGTMiy5KSkjRjxgzt2rWrW88xefJk1dXV6cyZMwqHw9q+fbu8Xm+8RkYXYrE/KysrdfToUR05ckQ///nPtXDhQj300EPxGhkXEYt9almWbr/9dn35y1/WbbfdFq9REYXu7N/S0lLt379fx44d07lz5/Taa69p1qxZdo3sWITMJcrv9ysUCl3wW8SHDh2qkydPdus5UlJS9Oijj+r666/X+PHjNWbMGM2ZMyce4+IiYrE/4Syx2Kc7duzQiy++qE2bNqmkpEQlJSV677334jEueqg7+zclJUWPPfaYpk+frpKSEv3whz/kE0sd4CMm6JXZs2fzCZc+6Pbbb7d7BMTAF7/4RYXDYbvHQC987Wtf09e+9jW7x3A03pG5ROXm5io5OVmnTp1qt/zUqVMaNmyYTVMhWuzPvod92rexf2OHkLlEpaWlaeLEiaquro4sC4fDqq6u1jXXXGPjZIgG+7PvYZ/2bezf2OHQUh927tw5HT58OHK9pqZG+/bt06BBg5Sfn6+ysjLNnz9fkyZNUmlpqaqqqtTY2KgFCxbYODU6w/7se9infRv7N0Hs/tgU4mfbtm2WpAsu8+fPj9znySeftPLz8620tDSrtLTUevPNN+0bGF1if/Y97NO+jf2bGPyuJQAAYCzOkQEAAMYiZAAAgLEIGQAAYCxCBgAAGIuQAQAAxiJkAACAsQgZAABgLEIGAAAYi5AB4CjTpk3T0qVL7R4DgCEIGQAAYCxCBgAAGIuQAeBYZ86c0be//W0NHDhQHo9Hs2fP1qFDhyK3f/zxx7rppps0cOBA9evXT+PGjdPmzZsjj7311ls1ePBgZWRkaMyYMXrmmWfs2hQAcZJi9wAA0Jnbb79dhw4d0iuvvKKsrCzdd999uvHGG3XgwAGlpqZq8eLFOn/+vLZv365+/frpwIED6t+/vySpoqJCBw4c0Guvvabc3FwdPnxYn376qc1bBCDWCBkAjtQWMDt27NC1114rSXr++eeVl5enTZs26Zvf/KZqa2v1jW98Q1deeaUk6fLLL488vra2VldffbUmTZokSSooKEj4NgCIPw4tAXAkn8+nlJQUTZkyJbIsJydHRUVF8vl8kqQlS5bokUce0dSpU7V8+XK9++67kfsuWrRIGzduVElJie69917t3Lkz4dsAIP4IGQDG+u53v6uPPvpIt912m9577z1NmjRJTz75pCRp9uzZ+vjjj3X33Xfr+PHjuuGGG3TPPffYPDGAWCNkADiS1+tVa2ur3nrrrciyTz75RAcPHlRxcXFkWV5env7lX/5FL730kn74wx9q/fr1kdsGDx6s+fPn67nnnlNVVZXWrVuX0G0AEH+cIwPAkcaMGaObb75ZCxcu1C9/+UtlZmbq/vvv18iRI3XzzTdLkpYuXarZs2dr7NixOnPmjLZt2yav1ytJeuihhzRx4kSNGzdOzc3NevXVVyO3Aeg7eEcGgGM988wzmjhxoubMmaNrrrlGlmVp8+bNSk1NlSSFQiEtXrxYXq9XX/nKVzR27Fg99dRTkqS0tDSVl5dr/Pjxuv7665WcnKyNGzfauTkA4sBlWZZl9xAAAADR4B0ZAABgLEIGAAAYi5ABAADGImQAAICxCBkAAGAsQgYAABiLkAEAAMYiZAAAgLEIGQAAYCxCBgAAGIuQAQAAxiJkAACAsf4PQCpQwnVN9OIAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "  \n",
    "\n",
    "sns.histplot(data=df, x=\"loss\", color=\"blue\", label=\"in\", log_scale=True)\n",
    "sns.histplot(data=df, x=\"out\", color=\"red\", label=\"out\", log_scale=True)\n",
    "\n",
    "plt.legend() \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "05bd3cc7-e9f6-438b-9e72-7a67d682b590",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "id": "3501d38f-7388-44cb-8b49-3c03c82ab8c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def imshow(img):\n",
    "    img = img\n",
    "    npimg = img\n",
    "    plt.imshow(npimg)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "id": "94652e56-d847-4409-89fa-99e1b48e52d5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "imshow(X_data[pri_risk_rank[idx]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "id": "9a280b28-71e2-4ac0-be7a-cab54c5af113",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Y_data[pri_risk_rank[idx]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "63075866-0819-4386-8e3d-ee79a873b1fd",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "opacus",
   "language": "python",
   "name": "opacus"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
